Fix world shader compilation for various input coordinate types

This commit is contained in:
Moritz Brückner 2020-10-10 21:28:36 +02:00
parent 6b797b75ae
commit 860594266c
3 changed files with 39 additions and 7 deletions

View file

@ -62,6 +62,8 @@ def create_world_shaders(world: bpy.types.World):
frag.add_in('vec3 normal')
frag.add_out('vec4 fragColor')
frag.write_attrib('vec3 n = normalize(normal);')
vert.write('''normal = nor;
vec4 position = SMVP * vec4(pos, 1.0);
gl_Position = vec4(position);''')
@ -157,7 +159,6 @@ def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: Sha
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(2.2));')
if '_EnvClouds' in world.world_defs:
frag.write_init('vec3 n = normalize(normal);')
frag.write('if (n.z > 0.0) fragColor.rgb = mix(fragColor.rgb, traceClouds(fragColor.rgb, n), clamp(n.z * 5.0, 0, 1));')
if '_EnvLDR' in world.world_defs:
@ -171,8 +172,22 @@ def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: Sha
if frag_bpos:
frag.add_in('vec3 bposition')
vert.add_out('vec3 bposition')
# Use normals for now
vert.write('bposition = nor;')
frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition')
if frag_mpos:
frag.add_in('vec3 mposition')
vert.add_out('vec3 mposition')
# Use normals for now
vert.write('mposition = nor;')
if frag.contains('texCoord') and not frag.contains('vec2 texCoord'):
frag.add_in('vec2 texCoord')
vert.add_out('vec2 texCoord')
# World has no UV map
vert.write('texCoord = vec2(1.0, 1.0);')
def parse_world_output(world: bpy.types.World, node_output: bpy.types.Node, frag: Shader, con: ShaderContext) -> bool:
"""Parse the world's output node. Return `False` when the node has

View file

@ -3,7 +3,7 @@ from typing import Union
import arm.material.cycles as c
import arm.material.cycles_functions as c_functions
from arm.material.parser_state import ParserState
from arm.material.parser_state import ParserState, ParserContext
from arm.material.shader import floatstr, vec3str
import arm.utils
@ -120,24 +120,42 @@ def parse_hairinfo(node: bpy.types.ShaderNodeHairInfo, out_socket: bpy.types.Nod
def parse_objectinfo(node: bpy.types.ShaderNodeObjectInfo, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
# Location
if out_socket == node.outputs[0]:
if state.context == ParserContext.WORLD:
return c.to_vec3((0.0, 0.0, 0.0))
return 'wposition'
# TODO: Color
elif out_socket == node.outputs[1]:
return 'wposition' # c.to_vec3(object.color)
if state.context == ParserContext.WORLD:
# Use world strength like Blender
background_node = c.node_by_type(state.world.node_tree.nodes, 'BACKGROUND')
if background_node is None:
return c.to_vec3((0.0, 0.0, 0.0))
return c.to_vec3([background_node.inputs[1].default_value] * 3)
# TODO: Implement object color in Iron
# state.curshader.add_uniform('vec3 objectInfoColor', link='_objectInfoColor')
# return 'objectInfoColor'
return c.to_vec3((1.0, 1.0, 1.0))
# Object Index
elif out_socket == node.outputs[2]:
if state.context == ParserContext.WORLD:
return '0.0'
state.curshader.add_uniform('float objectInfoIndex', link='_objectInfoIndex')
return 'objectInfoIndex'
# Material Index
elif out_socket == node.outputs[3]:
if state.context == ParserContext.WORLD:
return '0.0'
state.curshader.add_uniform('float objectInfoMaterialIndex', link='_objectInfoMaterialIndex')
return 'objectInfoMaterialIndex'
# Random
elif out_socket == node.outputs[4]:
if state.context == ParserContext.WORLD:
return '0.0'
state.curshader.add_uniform('float objectInfoRandom', link='_objectInfoRandom')
return 'objectInfoRandom'
@ -204,7 +222,9 @@ def parse_texcoord(node: bpy.types.ShaderNodeTexCoord, out_socket: bpy.types.Nod
elif out_socket == node.outputs[4]: # Camera
return 'vec3(0.0)' # 'vposition'
elif out_socket == node.outputs[5]: # Window
return 'vec3(0.0)' # 'wvpposition'
# TODO: Don't use gl_FragCoord here, it uses different axes on different graphics APIs
state.frag.add_uniform('vec2 screenSize', link='_screenSize')
return f'vec3(gl_FragCoord.xy / screenSize, 0.0)'
elif out_socket == node.outputs[6]: # Reflection
return 'vec3(0.0)'

View file

@ -351,7 +351,6 @@ def parse_tex_sky(node: bpy.types.ShaderNodeTexSky, out_socket: bpy.types.NodeSo
state.radiance_written = True
curshader.write_init('vec3 n = normalize(normal);')
curshader.write('float cos_theta = clamp(n.z, 0.0, 1.0);')
curshader.write('float cos_gamma = dot(n, hosekSunDirection);')
curshader.write('float gamma_val = acos(cos_gamma);')
@ -458,8 +457,6 @@ def parse_tex_environment(node: bpy.types.ShaderNodeTexEnvironment, out_socket:
if rpdat.arm_irradiance and rpdat.arm_radiance and not mobile_mat:
wrd.world_defs += '_Rad'
curshader.write_init('vec3 n = normalize(normal);')
return 'texture(envmap, envMapEquirect(n)).rgb * envmapStrength'