Proof of concept: 3D lighting on GPU

0 favourites
  • 15 posts
From the Asset Store
Immerse your quiz games with our 6 unique music loops, ranging from acoustic chill guitar to cute and upbeat style.
  • The newer 3D additions to C3 have opened up many visual possibilities to doing 3D games + C3 2D game logic / collision, etc.

    One drawback for the 3D rendering has been the issue that there is no lighting, so the 3D objects can sometimes look flat, losing the feeling of depth, because all the sides of a 3D shape have the same intensity and they can blend together.

    I would like to suggest one idea that could help, add a single light lighting shader as an option for the default vertex and fragment shaders that are using during predraw of 3D Shapes or 3D Meshes. Doing it on the GPU per fragment can make the lighting more subtle and does not take up CPU performance.

    To test this out just for proof of concept, I changed the C3 default vertex and fragment shaders. The vertex shader was changed to pass the position. The fragment shader was changed to calculate the fragment normal from pos based on dfdy and dfdx and then simple point / spotlight lighting with attenuation was applied (with a little bonus of creating normals from texture changes to make surfaces look a little more interesting, this could be removed.)

    It looks pretty decent and adds a nice feeling of depth to the 3D Shape and Mesh geometry.

    I think it could get complicated with more lights, but being able to define a single light would go a long way.

    Below is an example based on the latest complex terrain example (w/ higher resolution viewport and textures.)

    Subscribe to Construct videos now

    These could be applied when doing the pre draw for Mesh and 3D types of objects (3DShape and others).

    Ashley - if you want to do some quick testing, here is the simple test code, you can also contact me to get a test project if you are interested.

     return [`#version 300 es`, `in highp vec3 aPos;`, `in ${texPrecision} vec2 aTex;`, `out ${texPrecision} vec2 vTex;`, `out highp vec3 pos;`, `uniform highp mat4 matP;`, `uniform highp mat4 matMV;`, `void main(void) {`, ` gl_Position = matP * matMV * vec4(aPos, 1.0);`, ` vTex = aTex;`, ` pos = aPos;`, `}`].join("\n")
    
    
    return[
    "#version 300 es",
    "in mediump vec2 vTex;in highp vec3 pos;",
    "out lowp vec4 outColor;",
    "uniform lowp vec4 color;",
    "uniform lowp sampler2D samplerFront;",
    "uniform highp vec2 pixelSize;",
    "highp float luminance(in highp vec3 c)",
    "{",
    "	return dot(c, vec3(.2126, .7152, .0722));",
    "}",
    
    "highp vec3 normalColor(in highp vec2 uv, sampler2D nSampler)",
    "{",
    "highp vec2 s = pixelSize;",
    
    "	const highp vec2 size = vec2(2.0,0.0);",
    "	const highp vec3 off = vec3(-1.,0.,1.);",
    
    "highp float s11 = luminance(texture(nSampler,uv).xyz);",
    "highp float s01 = luminance(texture(nSampler, uv+off.xy*0.0001).xyz);",
    "highp float s10 = luminance(texture(nSampler, uv+off.yx*0.0001).xyz);",
    
    "highp vec3 va = (vec3(size.xy*0.001, s01 - s11));",
    "highp vec3 vb = (vec3(size.yx*0.001, s10 - s11));",
    
    "highp vec3 normalV = normalize(cross(va, vb));",
     
    "	return normalV;",
    "}",
    "void main(void) {",
    	"highp vec3 lightPos = vec3(300.,100.,800.);",
    	"highp vec3 lightDir = pos-lightPos;",
    	"highp float lightDist = length(lightDir);",
    	"lightDir = normalize(lightDir);",
    	"highp vec3 spotDir = vec3(0,0.7,-1.);",
    	"spotDir = normalize(spotDir);",
    	"highp vec3 dx = dFdx(pos);",
    	"highp vec3 dy = dFdy(pos);",
    	"highp vec3 worldSpaceNormal = normalize(cross(dx, dy));",
    	"worldSpaceNormal = worldSpaceNormal + 0.15 * normalColor(vTex, samplerFront);",
    	"worldSpaceNormal = normalize(worldSpaceNormal);",
    	"lowp vec4 tex = texture(samplerFront, vTex);",
    	"highp float light = dot(worldSpaceNormal,lightDir) * 0.5 + 0.5;",
    	"light = light*light;",
    	"highp float cutoff = 0.90; highp float edge = 0.3;",
    	"highp float spot = dot(spotDir, lightDir);",
    	"spot = spot < cutoff ? smoothstep(cutoff*(1.-edge), cutoff, spot) : 1.0;",
    	"light = light * spot;",
    	"light = light / (1.0 * 1.0 + lightDist * 0.00000001 + lightDist * lightDist * 0.000001);",
    	"light = light < 0.05 ? 0.05 : light;",
    	"outColor = vec4(light * tex.xyz, tex.a);",
    	"gl_FragDepth = (outColor.a == 0.0 ? 1.0 : gl_FragCoord.z);",
    "}"]
    .join("\n")
    
  • Fantastic work as always Mikal.

  • Another alternative is to have an option to have the vertex shader pass the pos value to the fragment shader and then allow the user to define the fragment shader used during the 3D Shape and Mesh predraw.

  • The youtube compression is horrible, so here's a still image from the same demo. Note the spotlight lighting (fringes out on the sides), distance attenuation of lighting and the variation of the lighting on the different faces of the blocks (3dshapes) and the terrain itself (mesh).

  • Another example, tighter spotlight.

  • Another example, use color parameters to control light position x,y,z of the light shader. Small impact on CPU, small impact on GPU.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Simple example w/ stock 3DShape, 3 lights, one dynamic.

  • That's so good!

    Ashley PLZ lol

  • It's weird that there's been zero response to this.

  • Isn’t no official response fine? Ashley only responds quick to shoot down an idea. We could also extrapolate what the possible reply could be based on previous replies on this topic. Typically we never know something was being worked on till it was basically done. There’s probably a reason for that. How many times has someone started working on something and for whatever reason couldn’t get it working? He could be working on something or doing nothing related to this.

  • I just want to support Mikal in this topic. He has long made a great contribution to the development of C3 and continues to do so. My respect

  • Isn’t no official response fine? Ashley only responds quick to shoot down an idea. We could also extrapolate what the possible reply could be based on previous replies on this topic. Typically we never know something was being worked on till it was basically done. There’s probably a reason for that. How many times has someone started working on something and for whatever reason couldn’t get it working? He could be working on something or doing nothing related to this.

    So, it seems a non-public response was made, likely to avoid the obvious and deserved community - what's left of it - fallout.

    For those wondering, the short version is: it would take effort, so no, despite it obviously being possible, given we all have eyeballs to see it working with a comparatively simple hack made by someone in their free time.

  • Here I am to once again explain that we get far, far more suggestions than we could possibly do. We have got probably 5+ year's worth of work posted in a few months to the latest suggestions platform. It is such a vast amount of suggestions that it is an enormous amount of work merely to review and respond to them all. Further, suggestions that look simple or obvious frequently turn out to be far more complicated than anticipated.

    I'm mostly just repeating what is described in more detail in this thread about the suggestions platform. That also explains why we do not guarantee a response to suggestions, and has a section saying "please do not try to claim your idea is simple or easy to do".

    I did have some email contact with someone else about this. The email thread originally started about a bug in the SDK, which was fixed, but then went on to a suggestion. It's not actually clear to me the topic discussed in that email thread is exactly the same as the thing described here. Anyway I ended up saying pretty much what I said here. I did some brief exploration of the feasibility - even though as I said there is no way we could possibly do even that for the volume of suggestions we get - and as far as I could tell from that, it would in fact be extremely complicated to do anything more at all in this area. Construct is first and foremost a 2D engine and adding more features that you'd typically see in a 3D engine quickly becomes very difficult, not least because the entire existing engine is geared for 2D. I would definitely prefer not to discuss such topics by email mainly because we don't have the resources to do that for everyone, and also because we have the suggestions platform to try to deal with that in a more consistent and transparent way.

    I realise that hearing a negative response to suggestions can be disappointing. I would emphasise once again this is usually due to the volume of suggestions and our limited resources, and nothing to do with the quality of the ideas. I'd do all the suggestions we got if possible, but it's just totally inconceivable. It's unreasonable to take an excessively negative interpretation of this, and so I must point out the Forum & Community guidelines, in particular this part, which if it continues may result in the thread being locked.

    Having a persistently antagonistic, cynical, combative, sceptical or complaining attitude. For example, no software is perfect, but if you continuously claim that our products are absolutely terrible in every way, you may quickly wear out your welcome.

  • This is not a complaint and I plan on asking further requests in the aha forum.

    A point of clarification, the reason this request is related to the request for not doing a pre-draw for 3D, is that this light effect will only work if 3D is not pre-drawn and a user effect can be the first shader used (lighting in this case, including in the shader the needed depth assignment regarding transparency and color/opacity changes).

    I understand it did not work out in the way Scirra tested this.

  • OMG Mikal its can be a game change for C3

    Its looks ready to port Half-Life to C3 💘

    very impressive and nice job!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)