From 12df3eba307759937dd3e2a7c80b45320e1eed68 Mon Sep 17 00:00:00 2001 From: Philipp Emanuel Weidmann Date: Sat, 13 Apr 2019 07:54:41 +0530 Subject: [PATCH] New render function Supports material properties and multiple light sources --- libcurv/frag.cc | 124 ++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/libcurv/frag.cc b/libcurv/frag.cc index 06bb8bf8..11d97751 100644 --- a/libcurv/frag.cc +++ b/libcurv/frag.cc @@ -205,69 +205,79 @@ void export_frag_3d( //" */\n" "}\n" - // Compute an ambient occlusion factor. - // pos: point on surface - // nor: normal of the surface at pos - // Yields a value clamped to [0,1] where 0 means no other surfaces - // around the point, and 1 means the point is occluded by other surfaces. - "float calcAO( in vec3 pos, in vec3 nor, float time )\n" - "{\n" - " float occ = 0.0;\n" - " float sca = 1.0;\n" - " for( int i=0; i<5; i++ )\n" - " {\n" - " float hr = 0.01 + 0.12*float(i)/4.0;\n" - " vec3 aopos = nor * hr + pos;\n" - " float dd = dist( vec4(aopos,time) );\n" - " occ += -(dd-hr)*sca;\n" - " sca *= 0.95;\n" - " }\n" - " return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); \n" + "struct Light {\n" + " vec3 position;\n" + " // One component per color channel\n" + " vec3 specular_intensity;\n" + " vec3 diffuse_intensity;\n" + " vec3 ambient_intensity;\n" + "};\n" + + "const Light lights[3] = Light[3](\n" + " Light(vec3(-10.0, -100.0, 100.0), vec3(1.5), vec3(1.5), vec3(0.25)),\n" + " Light(vec3( 0.0, 100.0, 100.0), vec3(2.0), vec3(2.0), vec3(0.25)),\n" + " Light(vec3( 20.0, 100.0, -100.0), vec3(1.5), vec3(1.5), vec3(0.5))\n" + ");\n" + + "struct Material {\n" + " // One component per color channel\n" + " vec3 specular_reflectivity;\n" + " vec3 diffuse_reflectivity;\n" + " vec3 ambient_reflectivity;\n" + " vec3 shininess;\n" + "};\n" + + "Material material(vec3 point, float time) {\n" + " return Material(vec3(1.5), vec3(1.2), vec3(0.5), vec3(15.0));\n" "}\n" - "// in ro: ray origin\n" - "// in rd: ray direction\n" - "// out: rgb colour\n" - "vec3 render( in vec3 ro, in vec3 rd, float time )\n" - "{ \n" - " //vec3 col = vec3(0.7, 0.9, 1.0) +rd.z*0.8;\n" - " vec3 col = background_colour;\n" - " vec4 res = castRay(ro,rd, time);\n" - " float t = res.x;\n" - " vec3 c = res.yzw;\n" - " if( c.x>=0.0 )\n" - " {\n" - " vec3 pos = ro + t*rd;\n" - " vec3 nor = calcNormal( pos, time );\n" - " vec3 ref = reflect( rd, nor );\n" - " \n" - " // material \n" - " col = c;\n" + "vec3 render(in vec3 ray_origin, in vec3 ray_direction, float time) {\n" + " vec4 result = castRay(ray_origin, ray_direction, time);\n" + " if (result.y < 0.0) {\n" + " return background_colour;\n" + " }\n" + "\n" + " float distance = result.x;\n" + " vec3 point = ray_origin + distance*ray_direction;\n" + " vec3 normal = calcNormal(point, time);\n" + " vec3 viewer_direction = -ray_direction;\n" "\n" - " // lighting \n" - " float occ = calcAO( pos, nor, time );\n" - " vec3 lig = normalize( vec3(-0.4, 0.6, 0.7) );\n" - " float amb = clamp( 0.5+0.5*nor.z, 0.0, 1.0 );\n" - " float dif = clamp( dot( nor, lig ), 0.0, 1.0 );\n" - " float bac = clamp( dot( nor, normalize(vec3(-lig.x,lig.y,0.0))), 0.0, 1.0 )*clamp( 1.0-pos.z,0.0,1.0);\n" - " float dom = smoothstep( -0.1, 0.1, ref.z );\n" - " float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 );\n" - " float spe = pow(clamp( dot( ref, lig ), 0.0, 1.0 ),16.0);\n" - " \n" - " vec3 lin = vec3(0.0);\n" - " lin += 1.30*dif*vec3(1.00,0.80,0.55);\n" - " lin += 2.00*spe*vec3(1.00,0.90,0.70)*dif;\n" - " lin += 0.40*amb*vec3(0.40,0.60,1.00)*occ;\n" - " lin += 0.50*dom*vec3(0.40,0.60,1.00)*occ;\n" - " lin += 0.50*bac*vec3(0.35,0.35,0.35)*occ;\n" - " lin += 0.25*fre*vec3(1.00,1.00,1.00)*occ;\n" - " vec3 iqcol = col*lin;\n" + " vec3 color = result.yzw;\n" + " Material material = material(point, time);\n" "\n" - " //col = mix( col, vec3(0.8,0.9,1.0), 1.0-exp( -0.0002*t*t*t ) );\n" - " col = mix(col,iqcol, 0.5);\n" // adjust contrast + " vec3 illumination = vec3(0.0);\n" + "\n" + " // Implementation follows https://en.wikipedia.org/wiki/Phong_reflection_model\n" + " for (int i = 0; i < lights.length(); i++) {\n" + " Light light = lights[i];\n" + "\n" + " illumination += material.ambient_reflectivity * light.ambient_intensity;\n" + "\n" + " vec3 light_direction = normalize(light.position - point);\n" + "\n" + " result = castRay(point, light_direction, time);\n" + " if (result.y < 0.0) {\n" + " // No part of the shape lies between the surface point\n" + " // and the light source, so directional light affects this point\n" + " vec3 reflection_direction = -reflect(light_direction, normal);\n" + "\n" + " float diffuse_term = dot(light_direction, normal);\n" + " if (diffuse_term > 0.0) {\n" + " illumination +=\n" + " material.diffuse_reflectivity * diffuse_term * light.diffuse_intensity;\n" + "\n" + " float specular_term = dot(reflection_direction, viewer_direction);\n" + " if (specular_term > 0.0) {\n" + " illumination +=\n" + " material.specular_reflectivity *\n" + " pow(vec3(specular_term), material.shininess) *\n" + " light.specular_intensity;\n" + " }\n" + " }\n" + " }\n" " }\n" "\n" - " return vec3( clamp(col,0.0,1.0) );\n" + " return mix(color, clamp(color*illumination, 0.0, 1.0), 0.5);\n" "}\n" "// Create a matrix to transform coordinates to look towards a given point.\n"