Light emission node.

This commit is contained in:
Lubos Lenco 2016-05-16 12:01:12 +02:00
parent 58b3c32f01
commit 7a4ce91202
11 changed files with 181 additions and 190 deletions

BIN
Assets/DroidSans.ttf Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Assets/checker_r.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,65 @@
package cycles.trait;
import kha.Image;
import kha.Video;
import kha.Assets;
import lue.Trait;
import lue.node.ModelNode;
class MovieTexture extends Trait {
var video:Video;
public static var image:Image;
public static var created = false;
var videoName:String;
function pow(pow: Int): Int {
var ret = 1;
for (i in 0...pow) ret *= 2;
return ret;
}
function getPower2(i: Int): Int {
var power = 0;
while(true) {
var res = pow(power);
if (res >= i) return res;
power++;
}
}
public function new(videoName:String) {
super();
this.videoName = videoName;
if (!created) {
created = true;
requestInit(init);
requestRender2D(render);
}
}
function init() {
video = Reflect.field(kha.Assets.videos,videoName);
video.play(true);
image = Image.createRenderTarget(getPower2(video.width()), getPower2(video.height()));
var n = cast(node, lue.node.ModelNode);
n.materials[0].contexts[0].textures[0] = image; // Override diffuse texture
}
function render(g:kha.graphics2.Graphics) {
g.end();
var g2 = image.g2;
g2.begin(true, 0xff000000);
g2.color = 0xffffffff;
g2.drawVideo(video, 0, 0, 1024, 512);
g2.end();
g.begin(false);
}
}

View file

@ -1104,7 +1104,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
def ExportMaterialRef(self, material, index, o):
if (not material in self.materialArray):
self.materialArray[material] = {"structName" : material.name}
o.material_refs.append(self.materialArray[material]["structName"])
def ExportParticleSystemRef(self, psys, index, o):
@ -1667,119 +1666,15 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
o.type = "spot"
#pointFlag = True
#spotFlag = True
# o.cycles.cast_shadow
#if (not object.use_shadow):
# self.Write(B", shadow = false")
#self.WriteNodeTable(objectRef)
# Export the light's color, and include a separate intensity if necessary.
# lc = Object()
# lc.attrib = "light"
# lc.size = 3
# lc.values = self.WriteColor(object.color)
# o.color = lc
o.color = self.WriteColor(object.color)
# intensity = object.energy
# if (intensity != 1.0):
# self.IndentWrite(B"Param (attrib = \"intensity\") {float {")
# self.WriteFloat(intensity)
# self.Write(B"}}\n")
# if (pointFlag):
# # Export a separate attenuation function for each type that's in use.
# falloff = object.falloff_type
# if (falloff == "INVERSE_LINEAR"):
# self.IndentWrite(B"Atten (curve = \"inverse\")\n", 0, True)
# self.IndentWrite(B"{\n")
# self.IndentWrite(B"Param (attrib = \"scale\") {float {", 1)
# self.WriteFloat(object.distance)
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n")
# elif (falloff == "INVERSE_SQUARE"):
# self.IndentWrite(B"Atten (curve = \"inverse_square\")\n", 0, True)
# self.IndentWrite(B"{\n")
# self.IndentWrite(B"Param (attrib = \"scale\") {float {", 1)
# self.WriteFloat(math.sqrt(object.distance))
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n")
# elif (falloff == "LINEAR_QUADRATIC_WEIGHTED"):
# if (object.linear_attenuation != 0.0):
# self.IndentWrite(B"Atten (curve = \"inverse\")\n", 0, True)
# self.IndentWrite(B"{\n")
# self.IndentWrite(B"Param (attrib = \"scale\") {float {", 1)
# self.WriteFloat(object.distance)
# self.Write(B"}}\n")
# self.IndentWrite(B"Param (attrib = \"constant\") {float {", 1)
# self.WriteFloat(1.0)
# self.Write(B"}}\n")
# self.IndentWrite(B"Param (attrib = \"linear\") {float {", 1)
# self.WriteFloat(object.linear_attenuation)
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n\n")
# if (object.quadratic_attenuation != 0.0):
# self.IndentWrite(B"Atten (curve = \"inverse_square\")\n")
# self.IndentWrite(B"{\n")
# self.IndentWrite(B"Param (attrib = \"scale\") {float {", 1)
# self.WriteFloat(object.distance)
# self.Write(B"}}\n")
# self.IndentWrite(B"Param (attrib = \"constant\") {float {", 1)
# self.WriteFloat(1.0)
# self.Write(B"}}\n")
# self.IndentWrite(B"Param (attrib = \"quadratic\") {float {", 1)
# self.WriteFloat(object.quadratic_attenuation)
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n")
# if (object.use_sphere):
# self.IndentWrite(B"Atten (curve = \"linear\")\n", 0, True)
# self.IndentWrite(B"{\n")
# self.IndentWrite(B"Param (attrib = \"end\") {float {", 1)
# self.WriteFloat(object.distance)
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n")
# if (spotFlag):
# # Export additional angular attenuation for spot lights.
# self.IndentWrite(B"Atten (kind = \"angle\", curve = \"linear\")\n", 0, True)
# self.IndentWrite(B"{\n")
# endAngle = object.spot_size * 0.5
# beginAngle = endAngle * (1.0 - object.spot_blend)
# self.IndentWrite(B"Param (attrib = \"begin\") {float {", 1)
# self.WriteFloat(beginAngle)
# self.Write(B"}}\n")
# self.IndentWrite(B"Param (attrib = \"end\") {float {", 1)
# self.WriteFloat(endAngle)
# self.Write(B"}}\n")
# self.IndentWrite(B"}\n")
# Parse nodes, only emission for now
for n in object.node_tree.nodes:
if n.type == 'EMISSION':
o.color = self.WriteColor(n.inputs[0].default_value)
o.strength = n.inputs[1].default_value / 1000.0
break
self.output.light_resources.append(o)
@ -1940,6 +1835,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
self.materialArray = {}
self.particleSystemArray = {}
self.boneParentArray = {}
self.materialToObjectDict = dict()
# Store used shaders and assets in this scene
ArmoryExporter.shader_references = []
@ -2124,6 +2020,14 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
if rb.use_margin:
x.parameters.append(rb.collision_margin)
o.traits.append(x)
# Map objects to materials, can be used in later stages
for i in range(len(node.material_slots)):
mat = node.material_slots[i].material
if mat in self.materialToObjectDict:
self.materialToObjectDict[mat].append(o)
else:
self.materialToObjectDict[mat] = [o]
def cb_export_camera(self, object, o):
#return
@ -2150,11 +2054,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
c.id = ArmoryExporter.material_ids #ArmoryExporter.pipeline_id
c.bind_constants = []
const = Object()
const.id = 'lighting'
const.bool = material.lighting_bool
c.bind_constants.append(const)
const = Object()
const.id = 'receiveShadow'
const.bool = material.receive_shadow
@ -2277,7 +2176,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
# TODO: gather defs from vertex data when custom shader is used
o.shader = material.custom_shader_name
def make_texture(self, id, image_node):
def make_texture(self, id, image_node, material):
tex = Object()
tex.id = id
if image_node.image is not None:
@ -2291,6 +2190,17 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
tex.mipmap_filter = 'linear'
tex.generate_mipmaps = True
#image_node.extension = 'Repeat'
if image_node.image.source == 'MOVIE': # Just append movie texture trait for now
movie_trait = Object()
movie_trait.type = 'Script'
movie_trait.class_name = 'MovieTexture'
movie_trait.parameters = [tex.name]
for o in self.materialToObjectDict[material]:
o.traits.append(movie_trait)
tex.source = 'movie'
tex.name = ''
else:
tex.name = ''
return tex
@ -2303,7 +2213,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
albedo_node = self.findNodeByLink(tree, node, albedo_input)
if albedo_node.type == 'TEX_IMAGE':
defs.append('_AMTex')
tex = self.make_texture('salbedo', albedo_node)
tex = self.make_texture('salbedo', albedo_node, material)
c.bind_textures.append(tex)
elif albedo_node.type == 'ATTRIBUTE': # Assume vcols for now
defs.append('_VCols')
@ -2318,7 +2228,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
if metalness_input.is_linked:
defs.append('_MMTex')
metalness_node = self.findNodeByLink(tree, node, metalness_input)
tex = self.make_texture('smm', metalness_node)
tex = self.make_texture('smm', metalness_node, material)
c.bind_textures.append(tex)
else:
col = metalness_input.default_value
@ -2331,7 +2241,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
if roughness_input.is_linked:
defs.append('_RMTex')
roughness_node = self.findNodeByLink(tree, node, roughness_input)
tex = self.make_texture('srm', roughness_node)
tex = self.make_texture('srm', roughness_node, material)
c.bind_textures.append(tex)
else:
col = roughness_input.default_value
@ -2345,14 +2255,14 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
if normal_input.is_linked:
defs.append('_NMTex')
normal_node = self.findNodeByLink(tree, node, normal_input)
tex = self.make_texture('snormal', normal_node)
tex = self.make_texture('snormal', normal_node, material)
c.bind_textures.append(tex)
# Occlusion Map
occlusion_input = node.inputs[1]
if occlusion_input.is_linked:
defs.append('_OMTex')
occlusion_node = self.findNodeByLink(tree, node, occlusion_input)
tex = self.make_texture('som', occlusion_node)
tex = self.make_texture('som', occlusion_node, material)
c.bind_textures.append(tex)
elif node.type == 'BSDF_TRANSPARENT':

View file

@ -32,7 +32,6 @@ def initProperties():
bpy.types.Camera.world_envtex_name = bpy.props.StringProperty(name="Environment Texture", default='')
bpy.types.Camera.world_envtex_num_mips = bpy.props.IntProperty(name="Number of mips", default=0)
# For material
bpy.types.Material.lighting_bool = bpy.props.BoolProperty(name="Lighting", default=True)
bpy.types.Material.receive_shadow = bpy.props.BoolProperty(name="Receive Shadow", default=True)
bpy.types.Material.custom_shader = bpy.props.BoolProperty(name="Custom Shader", default=False)
bpy.types.Material.custom_shader_name = bpy.props.StringProperty(name="Name", default="")
@ -97,7 +96,6 @@ class MatsPropsPanel(bpy.types.Panel):
layout = self.layout
mat = bpy.context.material
layout.prop(mat, 'lighting_bool')
layout.prop(mat, 'receive_shadow')
layout.prop(mat, 'custom_shader')
if mat.custom_shader:

View file

@ -12,4 +12,4 @@
"kha": "",
"lue": ""
}
}
}

View file

@ -24,6 +24,8 @@ uniform sampler2D senvmapBrdf;
// uniform mat4 invVP;
uniform mat4 LMVP;
uniform vec3 light;
uniform vec3 lightColor;
uniform float lightStrength;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform float time;
@ -436,6 +438,7 @@ void main() {
// Direct
vec3 direct = diffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH, dotLV) + specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH, dotLH);
direct = direct * lightColor * lightStrength;
// SSS only masked objects
if (texture(gbuffer0, texCoord).b == 2.0) {
@ -455,6 +458,7 @@ void main() {
vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;
vec3 indirectSpecular = prefilteredColor * (f0 * envBRDF.x + envBRDF.y);
vec3 indirect = indirectDiffuse + indirectSpecular;
indirect = indirect * lightColor * lightStrength;
vec4 outColor = vec4(vec3(direct * visibility + indirect * ao), 1.0);

View file

@ -21,6 +21,14 @@
"id": "light",
"link": "_lightPosition"
},
{
"id": "lightColor",
"link": "_lightColor"
},
{
"id": "lightStrength",
"link": "_lightStrength"
},
{
"id": "eye",
"link": "_cameraPosition"

View file

@ -37,8 +37,9 @@ uniform sampler2D smm;
uniform float metalness;
#endif
uniform bool lighting;
uniform bool receiveShadow;
uniform vec3 lightColor;
uniform float lightStrength;
// LTC
uniform vec3 light;
@ -495,83 +496,80 @@ void main() {
vec4 outColor;
if (lighting) {
vec3 v = normalize(eyeDir);
vec3 h = normalize(v + l);
vec3 v = normalize(eyeDir);
vec3 h = normalize(v + l);
float dotNV = max(dot(n, v), 0.0);
float dotNH = max(dot(n, h), 0.0);
float dotVH = max(dot(v, h), 0.0);
float dotLV = max(dot(l, v), 0.0);
float dotLH = max(dot(l, h), 0.0);
float dotNV = max(dot(n, v), 0.0);
float dotNH = max(dot(n, h), 0.0);
float dotVH = max(dot(v, h), 0.0);
float dotLV = max(dot(l, v), 0.0);
float dotLH = max(dot(l, h), 0.0);
#ifdef _MMTex
float metalness = texture(smm, texCoord).r;
float metalness = texture(smm, texCoord).r;
#endif
vec3 albedo = surfaceAlbedo(baseColor, metalness);
vec3 f0 = surfaceF0(baseColor, metalness);
vec3 albedo = surfaceAlbedo(baseColor, metalness);
vec3 f0 = surfaceF0(baseColor, metalness);
#ifdef _RMTex
float roughness = texture(srm, texCoord).r;
float roughness = texture(srm, texCoord).r;
#endif
// LTC
// const float rectSizeX = 2.5;
// const float rectSizeY = 1.2;
// vec3 ex = vec3(1, 0, 0)*rectSizeX;
// vec3 ey = vec3(0, 0, 1)*rectSizeY;
// vec3 p1 = light - ex + ey;
// vec3 p2 = light + ex + ey;
// vec3 p3 = light + ex - ey;
// vec3 p4 = light - ex - ey;
// float theta = acos(dotNV);
// vec2 tuv = vec2(roughness, theta/(0.5*PI));
// tuv = tuv*LUT_SCALE + LUT_BIAS;
// LTC
// const float rectSizeX = 2.5;
// const float rectSizeY = 1.2;
// vec3 ex = vec3(1, 0, 0)*rectSizeX;
// vec3 ey = vec3(0, 0, 1)*rectSizeY;
// vec3 p1 = light - ex + ey;
// vec3 p2 = light + ex + ey;
// vec3 p3 = light + ex - ey;
// vec3 p4 = light - ex - ey;
// float theta = acos(dotNV);
// vec2 tuv = vec2(roughness, theta/(0.5*PI));
// tuv = tuv*LUT_SCALE + LUT_BIAS;
// vec4 t = texture(sltcMat, tuv);
// mat3 Minv = mat3(
// vec3( 1, t.y, 0),
// vec3( 0, 0, t.z),
// vec3(t.w, 0, t.x)
// );
// vec3 ltcspec = LTC_Evaluate(n, v, position, Minv, p1, p2, p3, p4, true);
// ltcspec *= texture(sltcMag, tuv).a;
// vec3 ltcdiff = LTC_Evaluate(n, v, position, mat3(1), p1, p2, p3, p4, true);
// vec3 ltccol = ltcspec + ltcdiff * albedo;
// ltccol /= 2.0*PI;
// vec4 t = texture(sltcMat, tuv);
// mat3 Minv = mat3(
// vec3( 1, t.y, 0),
// vec3( 0, 0, t.z),
// vec3(t.w, 0, t.x)
// );
// vec3 ltcspec = LTC_Evaluate(n, v, position, Minv, p1, p2, p3, p4, true);
// ltcspec *= texture(sltcMag, tuv).a;
// vec3 ltcdiff = LTC_Evaluate(n, v, position, mat3(1), p1, p2, p3, p4, true);
// vec3 ltccol = ltcspec + ltcdiff * albedo;
// ltccol /= 2.0*PI;
// Direct
vec3 direct = diffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH, dotLV) + specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH, dotLH);
// Indirect
vec3 indirectDiffuse = texture(senvmapIrradiance, envMapEquirect(n)).rgb;
indirectDiffuse = pow(indirectDiffuse, vec3(2.2)) * albedo;
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipLevelFromRoughness(roughness);// + 1.0;
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
prefilteredColor = pow(prefilteredColor, vec3(2.2));
vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;
vec3 indirectSpecular = prefilteredColor * (f0 * envBRDF.x + envBRDF.y);
vec3 indirect = indirectDiffuse + indirectSpecular;
// Direct
vec3 direct = diffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH, dotLV) + specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH, dotLH);
direct = direct * lightColor * lightStrength;
// Indirect
vec3 indirectDiffuse = texture(senvmapIrradiance, envMapEquirect(n)).rgb;
indirectDiffuse = pow(indirectDiffuse, vec3(2.2)) * albedo;
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipLevelFromRoughness(roughness);// + 1.0;
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
prefilteredColor = pow(prefilteredColor, vec3(2.2));
vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;
vec3 indirectSpecular = prefilteredColor * (f0 * envBRDF.x + envBRDF.y);
vec3 indirect = indirectDiffuse + indirectSpecular;
indirect = indirect * lightColor * lightStrength;
outColor = vec4(vec3(direct * visibility + indirect), 1.0);
outColor = vec4(vec3(direct * visibility + indirect), 1.0);
#ifdef _OMTex
vec3 occlusion = texture(som, texCoord).rgb;
outColor.rgb *= occlusion;
vec3 occlusion = texture(som, texCoord).rgb;
outColor.rgb *= occlusion;
#endif
// LTC
// outColor.rgb = ltccol * 10.0 * visibility + indirect / 14.0;
}
else {
outColor = vec4(baseColor * visibility, 1.0);
}
// LTC
// outColor.rgb = ltccol * 10.0 * visibility + indirect / 14.0;
gl_FragColor = vec4(pow(outColor.rgb, vec3(1.0 / 2.2)), outColor.a);
}

View file

@ -41,6 +41,14 @@
"id": "light",
"link": "_lightPosition"
},
{
"id": "lightColor",
"link": "_lightColor"
},
{
"id": "lightStrength",
"link": "_lightStrength"
},
{
"id": "eye",
"link": "_cameraPosition"