2020-08-19 17:20:41 +02:00
|
|
|
from bpy.props import *
|
|
|
|
from bpy.types import Node
|
|
|
|
|
|
|
|
from arm.material.arm_nodes.arm_nodes import add_node
|
|
|
|
from arm.material.shader import Shader
|
|
|
|
|
|
|
|
|
|
|
|
class ShaderDataNode(Node):
|
|
|
|
"""Allows access to shader data such as uniforms and inputs."""
|
|
|
|
bl_idname = 'ArmShaderDataNode'
|
|
|
|
bl_label = 'Shader Data'
|
|
|
|
bl_icon = 'NONE'
|
|
|
|
|
|
|
|
input_type: EnumProperty(
|
|
|
|
items = [('input', 'Input', 'Shader Input'),
|
|
|
|
('uniform', 'Uniform', 'Uniform value')],
|
|
|
|
name='Input Type',
|
|
|
|
default='input',
|
|
|
|
description="The kind of data that should be retrieved")
|
|
|
|
|
|
|
|
input_source: EnumProperty(
|
|
|
|
items = [('frag', 'Fragment Shader', 'Take the input from the fragment shader'),
|
|
|
|
('vert', 'Vertex Shader', 'Take the input from the vertex shader and pass it through to the fragment shader')],
|
|
|
|
name='Input Source',
|
|
|
|
default='vert',
|
|
|
|
description="Where to take the input value from")
|
|
|
|
|
|
|
|
variable_type: EnumProperty(
|
|
|
|
items = [('int', 'int', 'int'),
|
|
|
|
('float', 'float', 'float'),
|
|
|
|
('vec2', 'vec2', 'vec2'),
|
|
|
|
('vec3', 'vec3', 'vec3'),
|
2020-08-27 23:22:24 +02:00
|
|
|
('vec4', 'vec4', 'vec4'),
|
|
|
|
('sampler2D', 'sampler2D', 'sampler2D')],
|
2020-08-19 17:20:41 +02:00
|
|
|
name='Variable Type',
|
|
|
|
default='vec3',
|
|
|
|
description="The type of the variable")
|
|
|
|
|
|
|
|
variable_name: StringProperty(name="Variable Name", description="The name of the variable")
|
|
|
|
|
|
|
|
def draw_buttons(self, context, layout):
|
|
|
|
col = layout.column(align=True)
|
|
|
|
col.label(text="Input Type:")
|
|
|
|
# Use a row to expand horizontally
|
|
|
|
col.row().prop(self, "input_type", expand=True)
|
|
|
|
|
|
|
|
split = layout.split(factor=0.5, align=True)
|
|
|
|
col_left = split.column()
|
|
|
|
col_right = split.column()
|
|
|
|
|
|
|
|
if self.input_type == "input":
|
|
|
|
col_left.label(text="Input Source")
|
|
|
|
col_right.prop(self, "input_source", text="")
|
|
|
|
|
|
|
|
col_left.label(text="Variable Type")
|
|
|
|
col_right.prop(self, "variable_type", text="")
|
|
|
|
col_left.label(text="Variable Name")
|
|
|
|
col_right.prop(self, "variable_name", text="")
|
|
|
|
|
|
|
|
def init(self, context):
|
|
|
|
self.outputs.new('NodeSocketColor', 'Color')
|
|
|
|
self.outputs.new('NodeSocketVector', 'Vector')
|
|
|
|
self.outputs.new('NodeSocketFloat', 'Float')
|
|
|
|
self.outputs.new('NodeSocketInt', 'Int')
|
|
|
|
|
|
|
|
def parse(self, frag: Shader, vert: Shader) -> str:
|
|
|
|
if self.input_type == "uniform":
|
|
|
|
frag.add_uniform(f'{self.variable_type} {self.variable_name}', link=self.variable_name)
|
2020-08-27 23:22:24 +02:00
|
|
|
|
|
|
|
if self.variable_type == "sampler2D":
|
|
|
|
frag.add_uniform('vec2 screenSize', link='_screenSize')
|
|
|
|
return f'texture({self.variable_name}, gl_FragCoord.xy / screenSize).rgb'
|
|
|
|
|
2020-08-19 17:20:41 +02:00
|
|
|
return self.variable_name
|
|
|
|
|
|
|
|
else:
|
|
|
|
if self.input_source == "frag":
|
|
|
|
frag.add_in(f'{self.variable_type} {self.variable_name}')
|
|
|
|
return self.variable_name
|
|
|
|
|
|
|
|
# Reroute input from vertex shader to fragment shader (input must exist!)
|
|
|
|
else:
|
|
|
|
vert.add_out(f'{self.variable_type} out_{self.variable_name}')
|
|
|
|
frag.add_in(f'{self.variable_type} out_{self.variable_name}')
|
|
|
|
|
|
|
|
vert.write(f'out_{self.variable_name} = {self.variable_name};')
|
|
|
|
return 'out_' + self.variable_name
|
|
|
|
|
|
|
|
|
|
|
|
add_node(ShaderDataNode, category='Armory')
|