Merge pull request #2239 from QuantumCoderQC/MatParamPerObject
Set material parameter on per object basis
This commit is contained in:
commit
616a0e230d
|
@ -1,40 +1,38 @@
|
|||
package armory.logicnode;
|
||||
|
||||
import iron.Scene;
|
||||
import iron.data.MaterialData;
|
||||
import iron.object.Object;
|
||||
import armory.trait.internal.UniformsManager;
|
||||
|
||||
class SetMaterialImageParamNode extends LogicNode {
|
||||
|
||||
static var registered = false;
|
||||
static var map = new Map<MaterialData, Map<String, kha.Image>>();
|
||||
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
iron.object.Uniforms.externalTextureLinks.push(textureLink);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var mat = inputs[1].get();
|
||||
if (mat == null) return;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
map.set(mat, entry);
|
||||
var object = inputs[1].get();
|
||||
if(object == null) return;
|
||||
|
||||
var perObject = inputs[2].get();
|
||||
if(perObject == null) perObject = false;
|
||||
|
||||
var mat = inputs[3].get();
|
||||
if(mat == null) return;
|
||||
|
||||
if(! perObject){
|
||||
UniformsManager.removeObjectFromMap(object, Texture);
|
||||
object = Scene.active.root;
|
||||
}
|
||||
|
||||
iron.data.Data.getImage(inputs[3].get(), function(image: kha.Image) {
|
||||
entry.set(inputs[2].get(), image); // Node name, value
|
||||
var img = inputs[5].get();
|
||||
if(img == null) return;
|
||||
iron.data.Data.getImage(img, function(image: kha.Image) {
|
||||
UniformsManager.setTextureValue(mat, object, inputs[4].get(), image);
|
||||
});
|
||||
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
static function textureLink(object: Object, mat: MaterialData, link: String): kha.Image {
|
||||
if (mat == null) return null;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) return null;
|
||||
return entry.get(link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,33 @@
|
|||
package armory.logicnode;
|
||||
|
||||
import iron.Scene;
|
||||
import iron.math.Vec4;
|
||||
import iron.data.MaterialData;
|
||||
import iron.object.Object;
|
||||
import armory.trait.internal.UniformsManager;
|
||||
|
||||
class SetMaterialRgbParamNode extends LogicNode {
|
||||
|
||||
static var registered = false;
|
||||
static var map = new Map<MaterialData, Map<String, Vec4>>();
|
||||
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
iron.object.Uniforms.externalVec3Links.push(vec3Link);
|
||||
}
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var mat = inputs[1].get();
|
||||
if (mat == null) return;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
map.set(mat, entry);
|
||||
var object = inputs[1].get();
|
||||
if(object == null) return;
|
||||
|
||||
var perObject = inputs[2].get();
|
||||
if(perObject == null) perObject = false;
|
||||
|
||||
var mat = inputs[3].get();
|
||||
if(mat == null) return;
|
||||
|
||||
if(! perObject){
|
||||
UniformsManager.removeObjectFromMap(object, Vector);
|
||||
object = Scene.active.root;
|
||||
}
|
||||
entry.set(inputs[2].get(), inputs[3].get()); // Node name, value
|
||||
|
||||
UniformsManager.setVec3Value(mat, object, inputs[4].get(), inputs[5].get());
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
|
||||
if (mat == null) return null;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) return null;
|
||||
return entry.get(link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,33 @@
|
|||
package armory.logicnode;
|
||||
|
||||
import iron.Scene;
|
||||
import iron.data.MaterialData;
|
||||
import iron.object.Object;
|
||||
import armory.trait.internal.UniformsManager;
|
||||
|
||||
class SetMaterialValueParamNode extends LogicNode {
|
||||
|
||||
static var registered = false;
|
||||
static var map = new Map<MaterialData, Map<String, Null<kha.FastFloat>>>();
|
||||
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
iron.object.Uniforms.externalFloatLinks.push(floatLink);
|
||||
}
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var mat = inputs[1].get();
|
||||
if (mat == null) return;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
map.set(mat, entry);
|
||||
var object = inputs[1].get();
|
||||
if(object == null) return;
|
||||
|
||||
var perObject = inputs[2].get();
|
||||
if(perObject == null) perObject = false;
|
||||
|
||||
var mat = inputs[3].get();
|
||||
if(mat == null) return;
|
||||
|
||||
if(! perObject){
|
||||
UniformsManager.removeObjectFromMap(object, Float);
|
||||
object = Scene.active.root;
|
||||
}
|
||||
entry.set(inputs[2].get(), inputs[3].get()); // Node name, value
|
||||
|
||||
UniformsManager.setFloatValue(mat, object, inputs[4].get(), inputs[5].get());
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
static function floatLink(object: Object, mat: MaterialData, link: String): Null<kha.FastFloat> {
|
||||
if (mat == null) return null;
|
||||
var entry = map.get(mat);
|
||||
if (entry == null) return null;
|
||||
return entry.get(link);
|
||||
}
|
||||
}
|
||||
|
|
321
Sources/armory/trait/internal/UniformsManager.hx
Normal file
321
Sources/armory/trait/internal/UniformsManager.hx
Normal file
|
@ -0,0 +1,321 @@
|
|||
package armory.trait.internal;
|
||||
|
||||
import iron.object.MeshObject;
|
||||
import iron.Trait;
|
||||
import kha.Image;
|
||||
import iron.math.Vec4;
|
||||
import iron.data.MaterialData;
|
||||
import iron.Scene;
|
||||
import iron.object.Object;
|
||||
import iron.object.Uniforms;
|
||||
|
||||
|
||||
class UniformsManager extends Trait{
|
||||
|
||||
static var floatsRegistered = false;
|
||||
static var floatsMap = new Map<Object, Map<MaterialData, Map<String, Null<kha.FastFloat>>>>();
|
||||
|
||||
static var vectorsRegistered = false;
|
||||
static var vectorsMap = new Map<Object, Map<MaterialData, Map<String, Vec4>>>();
|
||||
|
||||
static var texturesRegistered = false;
|
||||
static var texturesMap = new Map<Object, Map<MaterialData, Map<String, kha.Image>>>();
|
||||
|
||||
static var sceneRemoveInitalized = false;
|
||||
|
||||
public var unifromExists = false;
|
||||
|
||||
public function new(){
|
||||
super();
|
||||
|
||||
notifyOnInit(init);
|
||||
|
||||
notifyOnRemove(removeObject);
|
||||
|
||||
if(! sceneRemoveInitalized){
|
||||
|
||||
Scene.active.notifyOnRemove(removeScene);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
var materials = cast(object, MeshObject).materials;
|
||||
|
||||
for (material in materials){
|
||||
|
||||
var exists = registerShaderUniforms(material);
|
||||
if(exists) {
|
||||
unifromExists = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(! unifromExists) {
|
||||
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
|
||||
static function removeScene(){
|
||||
|
||||
removeObjectFromAllMaps(Scene.active.root);
|
||||
}
|
||||
|
||||
function removeObject() {
|
||||
|
||||
removeObjectFromAllMaps(object);
|
||||
|
||||
}
|
||||
|
||||
// Helper method to register float, vec3 and texture getter functions
|
||||
static function register(type: UniformType){
|
||||
|
||||
switch (type){
|
||||
case Float:{
|
||||
if(! floatsRegistered){
|
||||
floatsRegistered = true;
|
||||
Uniforms.externalFloatLinks.push(floatLink);
|
||||
}
|
||||
}
|
||||
|
||||
case Vector:{
|
||||
if(! vectorsRegistered){
|
||||
vectorsRegistered = true;
|
||||
Uniforms.externalVec3Links.push(vec3Link);
|
||||
}
|
||||
}
|
||||
|
||||
case Texture:{
|
||||
if(! texturesRegistered){
|
||||
texturesRegistered = true;
|
||||
Uniforms.externalTextureLinks.push(textureLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register and map shader uniforms if it is an armory shader parameter
|
||||
public static function registerShaderUniforms(material: MaterialData) : Bool {
|
||||
|
||||
var unifromExist = false;
|
||||
|
||||
if(! floatsMap.exists(Scene.active.root)) floatsMap.set(Scene.active.root, null);
|
||||
if(! vectorsMap.exists(Scene.active.root)) vectorsMap.set(Scene.active.root, null);
|
||||
if(! texturesMap.exists(Scene.active.root)) texturesMap.set(Scene.active.root, null);
|
||||
|
||||
for(context in material.shader.raw.contexts){ // For each context in shader
|
||||
for (constant in context.constants){ // For each constant in the context
|
||||
if(constant.is_arm_parameter){ // Chack if armory parameter
|
||||
|
||||
unifromExist = true;
|
||||
var object = Scene.active.root; // Map default uniforms to scene root
|
||||
|
||||
switch (constant.type){
|
||||
case "float":{
|
||||
var link = constant.link;
|
||||
var value:Float = constant.float;
|
||||
setFloatValue(material, object, link, value);
|
||||
register(Float);
|
||||
}
|
||||
|
||||
case "vec3":{
|
||||
|
||||
var vec = new Vec4();
|
||||
vec.x = constant.vec3.get(0);
|
||||
vec.y = constant.vec3.get(1);
|
||||
vec.z = constant.vec3.get(2);
|
||||
|
||||
setVec3Value(material, object, constant.link, vec);
|
||||
register(Vector);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (texture in context.texture_units){
|
||||
if(texture.is_arm_parameter){ // Chack if armory parameter
|
||||
|
||||
unifromExist = true;
|
||||
var object = Scene.active.root; // Map default texture to scene root
|
||||
|
||||
iron.data.Data.getImage(texture.default_image_file, function(image: kha.Image) {
|
||||
setTextureValue(material, object, texture.link, image);
|
||||
|
||||
});
|
||||
register(Texture);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return unifromExist;
|
||||
|
||||
}
|
||||
|
||||
// Method to set map Object -> Material -> Link -> FLoat
|
||||
public static function setFloatValue(material: MaterialData, object: Object, link: String, value: Null<kha.FastFloat>){
|
||||
|
||||
if(object == null || material == null || link == null) return;
|
||||
|
||||
var map = floatsMap;
|
||||
|
||||
var matMap = map.get(object);
|
||||
if (matMap == null) {
|
||||
matMap = new Map();
|
||||
map.set(object, matMap);
|
||||
}
|
||||
|
||||
var entry = matMap.get(material);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
matMap.set(material, entry);
|
||||
}
|
||||
|
||||
entry.set(link, value); // parameter name, value
|
||||
}
|
||||
|
||||
// Method to set map Object -> Material -> Link -> Vec3
|
||||
public static function setVec3Value(material: MaterialData, object: Object, link: String, value: Vec4){
|
||||
|
||||
if(object == null || material == null || link == null) return;
|
||||
|
||||
var map = vectorsMap;
|
||||
|
||||
var matMap = map.get(object);
|
||||
if (matMap == null) {
|
||||
matMap = new Map();
|
||||
map.set(object, matMap);
|
||||
}
|
||||
|
||||
var entry = matMap.get(material);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
matMap.set(material, entry);
|
||||
}
|
||||
|
||||
entry.set(link, value); // parameter name, value
|
||||
}
|
||||
|
||||
// Method to set map Object -> Material -> Link -> Texture
|
||||
public static function setTextureValue(material: MaterialData, object: Object, link: String, value: kha.Image){
|
||||
|
||||
if(object == null || material == null || link == null) return;
|
||||
|
||||
var map = texturesMap;
|
||||
|
||||
var matMap = map.get(object);
|
||||
if (matMap == null) {
|
||||
matMap = new Map();
|
||||
map.set(object, matMap);
|
||||
}
|
||||
|
||||
var entry = matMap.get(material);
|
||||
if (entry == null) {
|
||||
entry = new Map();
|
||||
matMap.set(material, entry);
|
||||
}
|
||||
|
||||
entry.set(link, value); // parameter name, value
|
||||
}
|
||||
|
||||
// Mehtod to get object specific material parameter float value
|
||||
static function floatLink(object: Object, mat: MaterialData, link: String): Null<kha.FastFloat> {
|
||||
|
||||
if(object == null || mat == null) return null;
|
||||
|
||||
if(! floatsMap.exists(object)){
|
||||
object = Scene.active.root;
|
||||
}
|
||||
|
||||
var material = floatsMap.get(object);
|
||||
if (material == null) return null;
|
||||
|
||||
var entry = material.get(mat);
|
||||
if (entry == null) return null;
|
||||
|
||||
return entry.get(link);
|
||||
}
|
||||
|
||||
// Mehtod to get object specific material parameter vec3 value
|
||||
static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
|
||||
|
||||
if(object == null || mat == null) return null;
|
||||
|
||||
if(! vectorsMap.exists(object)){
|
||||
object = Scene.active.root;
|
||||
}
|
||||
|
||||
var material = vectorsMap.get(object);
|
||||
if (material == null) return null;
|
||||
|
||||
var entry = material.get(mat);
|
||||
if (entry == null) return null;
|
||||
|
||||
return entry.get(link);
|
||||
}
|
||||
|
||||
// Mehtod to get object specific material parameter texture value
|
||||
static function textureLink(object: Object, mat: MaterialData, link: String): kha.Image {
|
||||
|
||||
if(object == null || mat == null) return null;
|
||||
|
||||
if(! texturesMap.exists(object)){
|
||||
object = Scene.active.root;
|
||||
}
|
||||
|
||||
var material = texturesMap.get(object);
|
||||
if (material == null) return null;
|
||||
|
||||
var entry = material.get(mat);
|
||||
if (entry == null) return null;
|
||||
|
||||
return entry.get(link);
|
||||
}
|
||||
|
||||
// Returns complete map of float value material paramets
|
||||
public static function getFloatsMap():Map<Object, Map<MaterialData, Map<String, Null<kha.FastFloat>>>>{
|
||||
|
||||
return floatsMap;
|
||||
}
|
||||
|
||||
// Returns complete map of vec3 value material paramets
|
||||
public static function getVectorsMap():Map<Object, Map<MaterialData, Map<String, Vec4>>>{
|
||||
|
||||
return vectorsMap;
|
||||
}
|
||||
|
||||
// Returns complete map of texture value material paramets
|
||||
public static function getTexturesMap():Map<Object, Map<MaterialData, Map<String, kha.Image>>>{
|
||||
|
||||
return texturesMap;
|
||||
}
|
||||
|
||||
// Remove all object specific material paramenter keys
|
||||
public static function removeObjectFromAllMaps(object: Object) {
|
||||
|
||||
floatsMap.remove(object);
|
||||
vectorsMap.remove(object);
|
||||
texturesMap.remove(object);
|
||||
|
||||
}
|
||||
|
||||
// Remove object specific material paramenter keys
|
||||
public static function removeObjectFromMap(object: Object, type: UniformType) {
|
||||
|
||||
switch (type){
|
||||
case Float: floatsMap.remove(object);
|
||||
|
||||
case Vector: vectorsMap.remove(object);
|
||||
|
||||
case Texture: texturesMap.remove(object);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@:enum abstract UniformType(Int) from Int to Int {
|
||||
var Float = 0;
|
||||
var Vector = 1;
|
||||
var Texture = 2;
|
||||
}
|
|
@ -2460,6 +2460,13 @@ Make sure the mesh only has tris/quads.""")
|
|||
else:
|
||||
self.material_to_object_dict[mat] = [bobject]
|
||||
self.material_to_arm_object_dict[mat] = [o]
|
||||
|
||||
# Add UniformsManager trait
|
||||
if type is NodeType.MESH:
|
||||
uniformManager = {}
|
||||
uniformManager['type'] = 'Script'
|
||||
uniformManager['class_name'] = 'armory.trait.internal.UniformsManager'
|
||||
o['traits'].append(uniformManager)
|
||||
|
||||
# Export constraints
|
||||
if len(bobject.constraints) > 0:
|
||||
|
|
|
@ -1,17 +1,43 @@
|
|||
from arm.logicnode.arm_nodes import *
|
||||
|
||||
class SetMaterialImageParamNode(ArmLogicTreeNode):
|
||||
"""TO DO."""
|
||||
"""Set an image value material parameter to the specified object.
|
||||
|
||||
@seeNode Get Scene Root
|
||||
|
||||
@input Object: Object whose material parameter should change. Use `Get Scene Root` node to set parameter globally.
|
||||
|
||||
@input Per Object:
|
||||
- `Enabled`: Set material parameter specific to this object. Global parameter will be ignored.
|
||||
- `Disabled`: Set parameter globally, including this object.
|
||||
|
||||
@input Material: Material whose parameter to be set.
|
||||
|
||||
@input Node: Name of the parameter.
|
||||
|
||||
@input Image: Name of the image.
|
||||
"""
|
||||
bl_idname = 'LNSetMaterialImageParamNode'
|
||||
bl_label = 'Set Material Image Param'
|
||||
arm_section = 'params'
|
||||
arm_version = 1
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(SetMaterialImageParamNode, self).init(context)
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketBool', 'Per Object')
|
||||
self.add_input('NodeSocketShader', 'Material')
|
||||
self.add_input('NodeSocketString', 'Node')
|
||||
self.add_input('NodeSocketString', 'Image')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
return NodeReplacement(
|
||||
'LNSetMaterialImageParamNode', self.arm_version, 'LNSetMaterialImageParamNode', 2,
|
||||
in_socket_mapping={0:0, 1:3, 2:4, 3:5}, out_socket_mapping={0:0}
|
||||
)
|
||||
|
|
|
@ -1,17 +1,43 @@
|
|||
from arm.logicnode.arm_nodes import *
|
||||
|
||||
class SetMaterialRgbParamNode(ArmLogicTreeNode):
|
||||
"""TO DO."""
|
||||
"""Set a color or vector value material parameter to the specified object.
|
||||
|
||||
@seeNode Get Scene Root
|
||||
|
||||
@input Object: Object whose material parameter should change. Use `Get Scene Root` node to set parameter globally.
|
||||
|
||||
@input Per Object:
|
||||
- `Enabled`: Set material parameter specific to this object. Global parameter will be ignored.
|
||||
- `Disabled`: Set parameter globally, including this object.
|
||||
|
||||
@input Material: Material whose parameter to be set.
|
||||
|
||||
@input Node: Name of the parameter.
|
||||
|
||||
@input Color: Color or vector input.
|
||||
"""
|
||||
bl_idname = 'LNSetMaterialRgbParamNode'
|
||||
bl_label = 'Set Material RGB Param'
|
||||
arm_section = 'params'
|
||||
arm_version = 1
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(SetMaterialRgbParamNode, self).init(context)
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketBool', 'Per Object')
|
||||
self.add_input('NodeSocketShader', 'Material')
|
||||
self.add_input('NodeSocketString', 'Node')
|
||||
self.add_input('NodeSocketColor', 'Color')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
return NodeReplacement(
|
||||
'LNSetMaterialRgbParamNode', self.arm_version, 'LNSetMaterialRgbParamNode', 2,
|
||||
in_socket_mapping={0:0, 1:3, 2:4, 3:5}, out_socket_mapping={0:0}
|
||||
)
|
||||
|
|
|
@ -1,17 +1,44 @@
|
|||
from arm.logicnode.arm_nodes import *
|
||||
|
||||
class SetMaterialValueParamNode(ArmLogicTreeNode):
|
||||
"""TO DO."""
|
||||
"""Set a float value material parameter to the specified object.
|
||||
|
||||
@seeNode Get Scene Root
|
||||
|
||||
@input Object: Object whose material parameter should change. Use `Get Scene Root` node to set parameter globally.
|
||||
|
||||
@input Per Object:
|
||||
- `Enabled`: Set material parameter specific to this object. Global parameter will be ignored.
|
||||
- `Disabled`: Set parameter globally, including this object.
|
||||
|
||||
@input Material: Material whose parameter to be set.
|
||||
|
||||
@input Node: Name of the parameter.
|
||||
|
||||
@input Float: float value.
|
||||
"""
|
||||
bl_idname = 'LNSetMaterialValueParamNode'
|
||||
bl_label = 'Set Material Value Param'
|
||||
arm_section = 'params'
|
||||
arm_version = 1
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(SetMaterialValueParamNode, self).init(context)
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketBool', 'Per Object')
|
||||
self.add_input('NodeSocketShader', 'Material')
|
||||
self.add_input('NodeSocketString', 'Node')
|
||||
self.add_input('NodeSocketFloat', 'Float')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
return NodeReplacement(
|
||||
'LNSetMaterialValueParamNode', self.arm_version, 'LNSetMaterialValueParamNode', 2,
|
||||
in_socket_mapping={0:0, 1:3, 2:4, 3:5}, out_socket_mapping={0:0}
|
||||
)
|
||||
|
|
|
@ -560,7 +560,7 @@ def to_uniform(inp: bpy.types.NodeSocket):
|
|||
def store_var_name(node: bpy.types.Node):
|
||||
return node_name(node.name) + '_store'
|
||||
|
||||
def texture_store(node, tex, tex_name, to_linear=False, tex_link=None):
|
||||
def texture_store(node, tex, tex_name, to_linear=False, tex_link=None, default_value=None, is_arm_mat_param=None):
|
||||
curshader = state.curshader
|
||||
|
||||
tex_store = store_var_name(node)
|
||||
|
@ -569,7 +569,7 @@ def texture_store(node, tex, tex_name, to_linear=False, tex_link=None):
|
|||
state.parsed.add(tex_store)
|
||||
mat_bind_texture(tex)
|
||||
state.con.add_elem('tex', 'short2norm')
|
||||
curshader.add_uniform('sampler2D {0}'.format(tex_name), link=tex_link)
|
||||
curshader.add_uniform('sampler2D {0}'.format(tex_name), link=tex_link, default_value=default_value, is_arm_mat_param=is_arm_mat_param)
|
||||
triplanar = node.projection == 'BOX'
|
||||
if node.inputs[0].is_linked:
|
||||
uv_name = parse_vector_input(node.inputs[0])
|
||||
|
|
|
@ -92,7 +92,13 @@ def parse_attribute(node: bpy.types.ShaderNodeAttribute, out_socket: bpy.types.N
|
|||
def parse_rgb(node: bpy.types.ShaderNodeRGB, out_socket: bpy.types.NodeSocket, state: ParserState) -> vec3str:
|
||||
if node.arm_material_param:
|
||||
nn = 'param_' + c.node_name(node.name)
|
||||
state.curshader.add_uniform(f'vec3 {nn}', link=f'{node.name}')
|
||||
v = out_socket.default_value
|
||||
value = []
|
||||
value.append(float(v[0]))
|
||||
value.append(float(v[1]))
|
||||
value.append(float(v[2]))
|
||||
is_arm_mat_param = True
|
||||
state.curshader.add_uniform(f'vec3 {nn}', link=f'{node.name}', default_value = value, is_arm_mat_param = is_arm_mat_param)
|
||||
return nn
|
||||
else:
|
||||
return c.to_vec3(out_socket.default_value)
|
||||
|
@ -351,7 +357,9 @@ def parse_lightpath(node: bpy.types.ShaderNodeLightPath, out_socket: bpy.types.N
|
|||
def parse_value(node: bpy.types.ShaderNodeValue, out_socket: bpy.types.NodeSocket, state: ParserState) -> floatstr:
|
||||
if node.arm_material_param:
|
||||
nn = 'param_' + c.node_name(node.name)
|
||||
state.curshader.add_uniform('float {0}'.format(nn), link='{0}'.format(node.name))
|
||||
value = c.to_vec1(node.outputs[0].default_value)
|
||||
is_arm_mat_param = True
|
||||
state.curshader.add_uniform('float {0}'.format(nn), link='{0}'.format(node.name), default_value=value, is_arm_mat_param=is_arm_mat_param)
|
||||
return nn
|
||||
else:
|
||||
return c.to_vec1(node.outputs[0].default_value)
|
||||
|
|
|
@ -114,15 +114,22 @@ def parse_tex_image(node: bpy.types.ShaderNodeTexImage, out_socket: bpy.types.No
|
|||
|
||||
tex_name = c.node_name(node.name)
|
||||
tex = c.make_texture(node, tex_name)
|
||||
tex_link = node.name if node.arm_material_param else None
|
||||
tex_link = None
|
||||
tex_default_file = None
|
||||
is_arm_mat_param = None
|
||||
if node.arm_material_param:
|
||||
tex_link = node.name
|
||||
is_arm_mat_param = True
|
||||
if tex['file'] is not None:
|
||||
tex_default_file = tex['file']
|
||||
|
||||
if tex is not None:
|
||||
state.curshader.write_textures += 1
|
||||
if use_color_out:
|
||||
to_linear = node.image is not None and node.image.colorspace_settings.name == 'sRGB'
|
||||
res = f'{c.texture_store(node, tex, tex_name, to_linear, tex_link=tex_link)}.rgb'
|
||||
res = f'{c.texture_store(node, tex, tex_name, to_linear, tex_link=tex_link, default_value=tex_default_file, is_arm_mat_param=is_arm_mat_param)}.rgb'
|
||||
else:
|
||||
res = f'{c.texture_store(node, tex, tex_name, tex_link=tex_link)}.a'
|
||||
res = f'{c.texture_store(node, tex, tex_name, tex_link=tex_link, default_value=tex_default_file, is_arm_mat_param=is_arm_mat_param)}.a'
|
||||
state.curshader.write_textures -= 1
|
||||
return res
|
||||
|
||||
|
|
|
@ -109,19 +109,27 @@ class ShaderContext:
|
|||
def get(self):
|
||||
return self.data
|
||||
|
||||
def add_constant(self, ctype, name, link=None):
|
||||
def add_constant(self, ctype, name, link=None, default_value=None, is_arm_mat_param=None):
|
||||
for c in self.constants:
|
||||
if c['name'] == name:
|
||||
return
|
||||
|
||||
c = { 'name': name, 'type': ctype }
|
||||
if link != None:
|
||||
c = { 'name': name, 'type': ctype}
|
||||
if link is not None:
|
||||
c['link'] = link
|
||||
if default_value is not None:
|
||||
if ctype == 'float':
|
||||
c['float'] = default_value
|
||||
if ctype == 'vec3':
|
||||
c['vec3'] = default_value
|
||||
if is_arm_mat_param is not None:
|
||||
c['is_arm_parameter'] = 'true'
|
||||
self.constants.append(c)
|
||||
|
||||
def add_texture_unit(self, name, link=None, is_image=None,
|
||||
addr_u=None, addr_v=None,
|
||||
filter_min=None, filter_mag=None, mipmap_filter=None):
|
||||
filter_min=None, filter_mag=None, mipmap_filter=None,
|
||||
default_value=None, is_arm_mat_param=None):
|
||||
for c in self.tunits:
|
||||
if c['name'] == name:
|
||||
return
|
||||
|
@ -141,6 +149,10 @@ class ShaderContext:
|
|||
c['filter_mag'] = filter_mag
|
||||
if mipmap_filter is not None:
|
||||
c['mipmap_filter'] = mipmap_filter
|
||||
if default_value is not None:
|
||||
c['default_image_file'] = default_value
|
||||
if is_arm_mat_param is not None:
|
||||
c['is_arm_parameter'] = 'true'
|
||||
|
||||
self.tunits.append(c)
|
||||
|
||||
|
@ -238,7 +250,7 @@ class Shader:
|
|||
def add_uniform(self, s, link=None, included=False, top=False,
|
||||
tex_addr_u=None, tex_addr_v=None,
|
||||
tex_filter_min=None, tex_filter_mag=None,
|
||||
tex_mipmap_filter=None):
|
||||
tex_mipmap_filter=None, default_value=None, is_arm_mat_param=None):
|
||||
ar = s.split(' ')
|
||||
# layout(RGBA8) image3D voxels
|
||||
utype = ar[-2]
|
||||
|
@ -257,7 +269,8 @@ class Shader:
|
|||
self.context.add_texture_unit(
|
||||
uname, link, is_image,
|
||||
tex_addr_u, tex_addr_v,
|
||||
tex_filter_min, tex_filter_mag, tex_mipmap_filter)
|
||||
tex_filter_min, tex_filter_mag, tex_mipmap_filter,
|
||||
default_value=default_value, is_arm_mat_param=is_arm_mat_param)
|
||||
else:
|
||||
# Prefer vec4[] for d3d to avoid padding
|
||||
if ar[0] == 'float' and '[' in ar[1]:
|
||||
|
@ -266,7 +279,7 @@ class Shader:
|
|||
elif ar[0] == 'vec4' and '[' in ar[1]:
|
||||
ar[0] = 'floats'
|
||||
ar[1] = ar[1].split('[', 1)[0]
|
||||
self.context.add_constant(ar[0], ar[1], link=link)
|
||||
self.context.add_constant(ar[0], ar[1], link=link, default_value=default_value, is_arm_mat_param=is_arm_mat_param)
|
||||
if top:
|
||||
if not included and s not in self.uniforms_top:
|
||||
self.uniforms_top.append(s)
|
||||
|
|
Loading…
Reference in a new issue