[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51141] branches/ge_harmony/source: Adding support for all the diffuse and specular shader models as well as their parameters to the inferred lighting mode .

Daniel Stokes kupomail at gmail.com
Sun Oct 7 09:56:23 CEST 2012


Revision: 51141
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51141
Author:   kupoman
Date:     2012-10-07 07:56:22 +0000 (Sun, 07 Oct 2012)
Log Message:
-----------
Adding support for all the diffuse and specular shader models as well as their parameters to the inferred lighting mode. The light shader is starting to get "heavy". Will probably need some optimization soon.

Modified Paths:
--------------
    branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_light_frag.glsl
    branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_prepass_frag.glsl
    branches/ge_harmony/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
    branches/ge_harmony/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp

Modified: branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_light_frag.glsl
===================================================================
--- branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_light_frag.glsl	2012-10-07 07:38:22 UTC (rev 51140)
+++ branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_light_frag.glsl	2012-10-07 07:56:22 UTC (rev 51141)
@@ -11,6 +11,22 @@
 #define CURVE		3
 #define SLIDERS		4
 
+//diff_shader
+#define DIFF_LAMBERT		0
+#define DIFF_ORENNAYAR	1
+#define DIFF_TOON		2
+#define DIFF_MINNAERT    3
+#define DIFF_FRESNEL     4
+
+//spec_shader
+#define SPEC_COOKTORR	0
+#define SPEC_PHONG		1
+#define SPEC_BLINN		2
+#define SPEC_TOON		3
+#define SPEC_WARDISO		4
+
+#define LN_511	6.23636959
+
 struct Light {
 	int type;
 	int falloff;
@@ -33,6 +49,212 @@
 uniform mat4 inv_proj_matrix;
 uniform vec2 bounds;
 
+void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is)
+{
+	vec3 h = normalize(v + l);
+	float nh = max(dot(n, h), 0.0);
+	float nv = max(dot(n, v), 0.0);
+	float realnl = dot(n, l);
+
+	if(realnl < 0.0) {
+		is = 0.0;
+	}
+	else if(nl < 0.0) {
+		is = 0.0;
+	}
+	else {
+		float vh = max(dot(v, h), 0.0);
+		float Lit_A = acos(realnl);
+		float View_A = acos(nv);
+
+		vec3 Lit_B = normalize(l - realnl*n);
+		vec3 View_B = normalize(v - nv*n);
+
+		float t = max(dot(Lit_B, View_B), 0.0);
+
+		float a, b;
+
+		if(Lit_A > View_A) {
+			a = Lit_A;
+			b = View_A;
+		}
+		else {
+			a = View_A;
+			b = Lit_A;
+		}
+
+		float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33)));
+		float B = 0.45*((rough*rough)/((rough*rough) + 0.09));
+
+		b *= 0.95;
+		is = nl*(A + (B * t * sin(a) * tan(b)));
+	}
+}
+
+void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is)
+{
+	float rslt = dot(n, l);
+	float ang = acos(rslt);
+
+	if(ang < size) is = 1.0;
+	else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0;
+	else is = 1.0 - ((ang - size)/tsmooth);
+}
+
+void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is)
+{
+	if(nl <= 0.0) {
+		is = 0.0;
+	}
+	else {
+		float nv = max(dot(n, v), 0.0);
+
+		if(darkness <= 1.0)
+			is = nl*pow(max(nv*nl, 0.1), darkness - 1.0);
+		else
+			is = nl*pow(1.0001 - nv, darkness - 1.0);
+	}
+}
+
+float fresnel_fac(vec3 view, vec3 vn, float grad, float fac)
+{
+	float t1, t2;
+	float ffac;
+
+	if(fac==0.0) {
+		ffac = 1.0;
+	}
+	else {
+		t1= dot(view, vn);
+		if(t1>0.0)  t2= 1.0+t1;
+		else t2= 1.0-t1;
+
+		t2= grad + (1.0-grad)*pow(t2, fac);
+
+		if(t2<0.0) ffac = 0.0;
+		else if(t2>1.0) ffac = 1.0;
+		else ffac = t2;
+	}
+
+	return ffac;
+}
+
+void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is)
+{
+	is = fresnel_fac(lv, vn, fac_i, fac);
+}
+
+void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t)
+{
+	lv += view;
+	lv = normalize(lv);
+
+	t = dot(vn, lv);
+	t = 0.5*t + 0.5;
+
+	t = visifac*spec*pow(t, hard);
+}
+
+void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
+{
+	vec3 h = normalize(l + v);
+	float rslt = max(dot(h, n), 0.0);
+
+	specfac = pow(rslt, hard);
+}
+
+void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
+{
+	vec3 h = normalize(v + l);
+	float nh = dot(n, h);
+
+	if(nh < 0.0) {
+		specfac = 0.0;
+	}
+	else {
+		float nv = max(dot(n, v), 0.0);
+		float i = pow(nh, hard);
+
+		i = i/(0.1+nv);
+		specfac = i;
+	}
+}
+
+void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac)
+{
+	if(refrac < 1.0) {
+		specfac = 0.0;
+	}
+	else if(spec_power == 0.0) {
+		specfac = 0.0;
+	}
+	else {
+		if(spec_power<100.0)
+			spec_power= sqrt(1.0/spec_power);
+		else
+			spec_power= 10.0/spec_power;
+
+		vec3 h = normalize(v + l);
+		float nh = dot(n, h);
+		if(nh < 0.0) {
+			specfac = 0.0;
+		}
+		else {
+			float nv = max(dot(n, v), 0.01);
+			float nl = dot(n, l);
+			if(nl <= 0.01) {
+				specfac = 0.0;
+			}
+			else {
+				float vh = max(dot(v, h), 0.01);
+
+				float a = 1.0;
+				float b = (2.0*nh*nv)/vh;
+				float c = (2.0*nh*nl)/vh;
+
+				float g = 0.0;
+
+				if(a < b && a < c) g = a;
+				else if(b < a && b < c) g = b;
+				else if(c < a && c < b) g = c;
+
+				float p = sqrt(((refrac * refrac)+(vh*vh)-1.0));
+				float f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1.0+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0))));
+				float ang = acos(nh);
+
+				specfac = max(f*g*exp((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0);
+			}
+		}
+	}
+}
+
+#define M_PI 3.14159265358979323846
+void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac)
+{
+	vec3 h = normalize(l + v);
+	float nh = max(dot(n, h), 0.001);
+	float nv = max(dot(n, v), 0.001);
+	float nl = max(dot(n, l), 0.001);
+	float angle = tan(acos(nh));
+	float alpha = max(rms, 0.001);
+
+	specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
+}
+
+void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac)
+{
+	vec3 h = normalize(l + v);
+	float rslt = dot(h, n);
+	float ang = acos(rslt);
+
+	if(ang < size) rslt = 1.0;
+	else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0;
+	else rslt = 1.0 - ((ang - size)/tsmooth);
+
+	specfac = rslt;
+}
+
+
 void main()
 {
 	vec3 L;
@@ -40,6 +262,7 @@
 	
 	vec2 texcoord = gl_FragCoord.xy/bounds.xy;
 	vec4 gbuffer = texture2D(prepass1, texcoord);
+	vec4 mbuffer = texture2D(prepass2, texcoord);
 
 	vec3 N = vec3(gbuffer.rg, 0.0);
 	N = 2 * (N - vec3(0.5, 0.5, 0.0));
@@ -55,7 +278,9 @@
 	proj.w = 1.0;
 	proj = inv_proj_matrix * proj;
 	V.xyz = proj.xyz/proj.w;
+	vec3 view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(-V): vec3(0.0, 0.0, -1.0);
 	
+	// Light position/orientation and attenuation
 	if (light.type == SUN || light.type == HEMI)
 		L = light.vector;
 	else {
@@ -75,17 +300,53 @@
 		attenuation *= max((light.dist - dist), 0.0)/light.dist;
 	}
 	
-	vec3 H = normalize(L - V);
+	int matid = int(gbuffer.a*65535);
+	int diff_shader = matid / 16;
+	int spec_shader = matid - (diff_shader*16);
 	
-	float lambert = max(dot(N, normalize(L)), 0.0);
+	// Diffuse term
+	float diff_term = 0.0;
+	float diff_param1 = mbuffer.r * 10.0;
+	float diff_param2 = mbuffer.g * 10.0;
+	L = normalize(L);
+	float lambert = max(dot(N, L), 0.0);
 	if (light.type == HEMI)
-		lambert = 0.5*lambert + 0.5;
-		
-	float phong = pow(max(dot(H, N), 0.0), 50.0);
-		
-	vec3 diff = light.color * light.energy * lambert * attenuation;
-	float spec = length(light.energy) * phong * attenuation;
-
+		diff_term = 0.5*lambert + 0.5;
+	else if (diff_shader == DIFF_LAMBERT)
+		diff_term = lambert;
+	else if (diff_shader == DIFF_ORENNAYAR)
+		shade_diffuse_oren_nayer(lambert, N, L, V, diff_param1, diff_term);
+	else if (diff_shader == DIFF_TOON)
+		shade_diffuse_toon(N, L, V, diff_param1, diff_param2, diff_term);
+	else if (diff_shader == DIFF_MINNAERT)
+		shade_diffuse_minnaert(lambert, N, V, diff_param1, diff_term);
+	else if (diff_shader == DIFF_FRESNEL)
+		shade_diffuse_fresnel(N, L, V, diff_param1, diff_param2, diff_term);
+	
+	// Specular term
+	float hardness = exp(LN_511 * mbuffer.b);
+	float spec_param = mbuffer.a * 10.0;
+	float spec_term = 0.0;
+	if (light.type == HEMI)
+		shade_hemi_spec(N, L, view, 1.0, hardness, 1.0, spec_term);
+	else if (spec_shader == SPEC_PHONG)
+		shade_phong_spec(N, L, view, hardness, spec_term);
+	else if (spec_shader == SPEC_COOKTORR)
+		shade_cooktorr_spec(N, L, view, hardness, spec_term);
+	else if (spec_shader == SPEC_BLINN)
+		shade_blinn_spec(N, L, view, spec_param, hardness, spec_term);
+	else if (spec_shader == SPEC_WARDISO)
+		shade_wardiso_spec(N, L, view, spec_param, spec_term);
+	else if (spec_shader == SPEC_TOON)
+	{
+		hardness = mbuffer.b * 10.0;
+		shade_toon_spec(N, L, view, hardness, spec_param, spec_term);
+	}
+	
+	// Factor in light properties
+	vec3 diff = light.color * light.energy * diff_term * attenuation;
+	float spec = length(light.energy) * spec_term * attenuation;
+	
 	gl_FragData[0] = vec4(diff, spec);
 }
 

Modified: branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_prepass_frag.glsl
===================================================================
--- branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_prepass_frag.glsl	2012-10-07 07:38:22 UTC (rev 51140)
+++ branches/ge_harmony/source/blender/gpu/shaders/gpu_shader_prepass_frag.glsl	2012-10-07 07:56:22 UTC (rev 51141)
@@ -2,11 +2,24 @@
 varying vec3 varnormal;
 varying vec3 varposition;
 varying vec2 vardepth;
+uniform float mat_id;
 
+uniform float diff_param1;
+uniform float diff_param2;
+
+uniform float hardness;
+uniform float spec_param;
+
 void main()
 {
 	vec3 n = normalize(varnormal + vec3(0.0, 0.0, 1.0));
 	n = 0.5 * n + vec3(0.5, 0.5, 0.5);
     gl_FragData[0].rg = n.xy;
 	gl_FragData[0].b = vardepth.x / vardepth.y;
+	gl_FragData[0].a = mat_id;
+	
+	gl_FragData[1].r = diff_param1;
+	gl_FragData[1].g = diff_param2;
+	gl_FragData[1].b = hardness;
+	gl_FragData[1].a = spec_param;
 }
\ No newline at end of file

Modified: branches/ge_harmony/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
===================================================================
--- branches/ge_harmony/source/gameengine/Ketsji/KX_BlenderMaterial.cpp	2012-10-07 07:38:22 UTC (rev 51140)
+++ branches/ge_harmony/source/gameengine/Ketsji/KX_BlenderMaterial.cpp	2012-10-07 07:56:22 UTC (rev 51141)
@@ -25,6 +25,7 @@
 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
 
 #include "GPU_draw.h"
+#include "GPU_extensions.h"
 
 #include "STR_HashedString.h"
 
@@ -603,6 +604,52 @@
 
 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
 {
+	if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_OVERRIDE)
+	{
+		Material *mat = mMaterial->material;
+		int bind;
+		GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_PREPASS);
+
+		bind = GPU_shader_get_uniform(shader, "mat_id");
+		int id = (mat->diff_shader << 4) + mat->spec_shader;
+		float fid = id/65335.0;
+		GPU_shader_uniform_vector(shader, bind, 1, 1, &fid);
+
+		float dparam1=0.0, dparam2=0.0;
+		if (mat->diff_shader == MA_DIFF_TOON || mat->diff_shader == MA_DIFF_FRESNEL)
+		{
+			dparam1 = mat->param[0] / 10.0;
+			dparam2 = mat->param[1] / 10.0;
+		}
+		else if (mat->diff_shader == MA_DIFF_ORENNAYAR)
+			dparam1 = mat->roughness / 10.0;
+		else if (mat->diff_shader == MA_DIFF_MINNAERT)
+			dparam1 = mat->darkness / 10.0;
+
+		bind = GPU_shader_get_uniform(shader, "diff_param1");

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list