opengl,directx,glsl,shader,hlsl , Shader - Simple SSS lighting issue


Shader - Simple SSS lighting issue

Question:

Tag: opengl,directx,glsl,shader,hlsl

I am trying to create a simple subsurface scattering effect using a shader but I am facing a small issue.

Look at those screenshots. The three images represents three lighting states (above surface, really close to surface, subsurface) with various lighting colors (red and blue) and always the same subsurface color (red).

enter image description here

As you might notice when the light is above the surface and really close to this surface its influence appears to minimize which is the expected behavior. But the problem is that is behaves the same for the subsurface part, this is normal according to my shader code but in my opinion the subsurface light influence should be higher when going close to the surface. I suggest you to look at the screenshot for the expected result.

How can I do that ?

Here is the simplified shader code.

half ndotl = max(0.0f, dot(normalWorld, lightDir));
half inversendotl = max(0.0f, dot(normalWorld, -lightDir));
half3 lightColor = _LightColor0.rgb * ndotl; // This is the normal light color calculation
half3 subsurfacecolor = translucencyColor.rgb * inversendotl; // This is the subsurface color
half3 topsubsurfacecolor = translucencyColor.rgb; // This is used for adding subsurface color to top surface
final = subsurfacescolor + lerp(lightColor, topsubsurfacecolor * 0.5, 1 - ndotl - inversendotl);

Answer:

The way, how you have implemented subsurface scattering effect is very rough. It is hard to achieve nice result using so simple approach. Staying within selected approach, I would recommend you the following things:

So, the modified version of your shader would be as follows:

half3 toLightVector = u_lightPos - v_fragmentPos;
half lightDistanceSQ = dot(toLightVector, toLightVector);
half3 lightDir = normalize(toLightVector);
half ndotl = max(0.0, dot(v_normal, lightDir));
half inversendotl = step(0.0, dot(v_normal, -lightDir));
half3 lightColor = _LightColor0.rgb * ndotl / lightDistanceSQ  * _LightIntensity0; 
half3 subsurfacecolor = translucencyColor.rgb * inversendotl / lightDistanceSQ  * _LightIntensity0;
half3 final = subsurfacecolor + lightColor;

Where u_lightPos - uniform that contains position of the light source, v_fragmentPos - varying that contains position of the fragment.

Here is an example in glsl using three.js:

   var container;
   var camera, scene, renderer;
   var sssMesh;
   var lightSourceMesh;
   var sssUniforms;

   var clock = new THREE.Clock();

   init();
   animate();

   function init() {
     container = document.getElementById('container');

     camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 3000);
     camera.position.z = 4;
     camera.position.y = 2;
     camera.rotation.x = -0.45;

     scene = new THREE.Scene();

     var boxGeometry = new THREE.CubeGeometry(0.75, 0.75, 0.75);

     var lightSourceGeometry = new THREE.CubeGeometry(0.1, 0.1, 0.1);

     sssUniforms = {
       u_lightPos: {
         type: "v3",
         value: new THREE.Vector3()
       }
     };

     var sssMaterial = new THREE.ShaderMaterial({
       uniforms: sssUniforms,
       vertexShader: document.getElementById('vertexShader').textContent,
       fragmentShader: document.getElementById('fragment_shader').textContent
     });

     var lightSourceMaterial = new THREE.MeshBasicMaterial();

     sssMesh = new THREE.Mesh(boxGeometry, sssMaterial);
     sssMesh.position.x = 0;
     sssMesh.position.y = 0;
     scene.add(sssMesh);

     lightSourceMesh = new THREE.Mesh(lightSourceGeometry, lightSourceMaterial);
     lightSourceMesh.position.x = 0;
     lightSourceMesh.position.y = 0;
     scene.add(lightSourceMesh);

     renderer = new THREE.WebGLRenderer();
     container.appendChild(renderer.domElement);

     onWindowResize();

     window.addEventListener('resize', onWindowResize, false);

   }

   function onWindowResize(event) {
     camera.aspect = window.innerWidth / window.innerHeight;
     camera.updateProjectionMatrix();
     renderer.setSize(window.innerWidth, window.innerHeight);
   }

   function animate() {
     requestAnimationFrame(animate);
     render();
   }

   function render() {
     var delta = clock.getDelta();
     var lightHeight = Math.sin(clock.elapsedTime * 1.0) * 0.5 + 0.7;
     lightSourceMesh.position.y = lightHeight;
     sssUniforms.u_lightPos.value.y = lightHeight;
     sssMesh.rotation.y += delta * 0.5;
     renderer.render(scene, camera);
   }
    body {

      color: #ffffff;

      background-color: #050505;

      margin: 0px;

      overflow: hidden;

    }
    <script src="http://threejs.org/build/three.min.js"></script>
    <div id="container"></div>

    <script id="fragment_shader" type="x-shader/x-fragment">

    varying vec3 v_fragmentPos;
    varying vec3 v_normal;
    uniform vec3 u_lightPos;
    void main(void)
    {
        vec3 _LightColor0 = vec3(1.0,0.5,0.5);  
        float _LightIntensity0 = 0.2;
        vec3 translucencyColor = vec3(0.8,0.2,0.2);
        vec3 toLightVector = u_lightPos - v_fragmentPos;
        float lightDistanceSQ = dot(toLightVector, toLightVector);
        vec3 lightDir = normalize(toLightVector);
    	float ndotl = max(0.0, dot(v_normal, lightDir));
    	float inversendotl = step(0.0, dot(v_normal, -lightDir));
        vec3 lightColor = _LightColor0.rgb * ndotl / lightDistanceSQ * _LightIntensity0; 
    	vec3 subsurfacecolor = translucencyColor.rgb * inversendotl / lightDistanceSQ * _LightIntensity0;
    	vec3 final = subsurfacecolor + lightColor;
    	gl_FragColor=vec4(final,1.0);
    }

    </script>

    <script id="vertexShader" type="x-shader/x-vertex">

    varying vec3 v_fragmentPos;
    varying vec3 v_normal;
                
    void main()
    {
    	vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        v_fragmentPos =  (modelMatrix * vec4( position, 1.0 )).xyz;
        v_normal =  (modelMatrix * vec4( normal, 0.0 )).xyz;
    	gl_Position = projectionMatrix * mvPosition;
    }

    </script>

There are large amount of different techniques of simulation of SSS. Texture-space diffusion and shadowmap-based translucency are the most frequently used techniques.

Check this article from GPU Gems, it describes mentioned techniques. Also, you can find interesting this presentation from EA. It mentions approach that is very close to yours for rendering plants.

Spherical harmonics also works well for static geometry, but this approach is very complicated and it needs precomputed irradiance transfer. Check this article, that shows use of spherical harmonics to approximate SSS.


Related:


GLSL - program link error: Slot 0 unavailable from layout location request


c++,opengl,glsl
I'm trying to draw a textured quad copying some code from a tutorial but I'm afraid there is a problem with the shaders. Both the vertex shader and the fragment shader compilation works, but when linking the program I get the error: ERROR: Active attribute aliasing. Slot 0 unavailable for...

OpenGL stops rendering, possibly after an update


c++,opengl,glfw
I am working on a small OpenGL project using the GLFW library. Everything was fine until from one day, I can't get it to render anything except the background. So I loaded up an older version, which I am sure worked just fine and the same thing happens. I then...

DirectWrite align text center


c++,text,directx,direct2d,directwrite
I am trying to align center the text I have to draw. I use ID2D1RenderTarget::DrawTextLayout method. The problemn is that if I set the text horizontal alignment to DWRITE_TEXT_ALIGNMENT_LEADING (the default value) the text is drawn proberly, but if I change this value to DWRITE_TEXT_ALIGNMENT_CENTER the text is shifted right....

Effect of rendering calls on performance


c++,opengl
Consider a situation , Case 1 : I am giving opengl calls to draw the world by drawing all polygons. So all polygons will be drawn according to all objects exist. (Considered all translation rotation). Case 2 : I will allow only polygons that are in field of view(FOV) of...

OpengGL face culing for selected faces


opengl
I'm importing geometry data from a file and the objects could be split in two categories: open or closed. If all of them were closed, I could just cull the backfaces, but since some of them are not closed, I cannot, because the user could see only the front faces....

Changing texture parameters at runtime


c++,opengl
I am an OpenGL beginner and I have built a small engine for a universitary course. Now one constraint/feature I need to implement is to change the texture quality (interpolation) at runtime. So instead of e.g.: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); it should be changed to mipmaps glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) Now I...

Unable to render a texture on a quad


c++,opengl,textures,texturing
I am trying to program a simple game in C++ using OpenGL for graphics. In my game, I have objects that are rendered onscreen as a white square. I would like to be able to bind an image as a texture to these objects, so that I can render an...

Linker error compiling DX10 program in Visual Studio 2015


visual-studio,visual-c++,linker,directx
I am trying to compile old program which works with DirectX 10. Full list of libraries used: #pragma comment(lib, "d3d10.lib") #pragma comment(lib, "d3dx10.lib") #pragma comment(lib, "dxgi.lib") #pragma comment(lib, "dxerr.lib") #pragma comment( lib, "dxguid.lib" ) Linker error: dxerr.lib(dxerrw.obj) : error LNK2019: unresolved external symbol _vsnwprintf referenced in function "long __cdecl StringVPrintfWorkerW(unsigned...

Ambient and Specular lighting not working correctly in GLSL


opengl,glsl,lighting,phong
In my lighting scene, for some reason the ambient lighting isn't working at all. The whole model is the same brightness, no matter which way it is facing. I tried getting rid of the attenuation but it still has the same results. Along with that, the specular lighting is always...

The order of the linked libraries C++ linker


c++,opengl,opencl
I was debugging a project that depends on a set of libraries including libfreenect, OpenGL and OpenCL. The problem is that a black screen was the output. As a debugging option, I have removed the OpenCL code and the linked library completely trying to make sure that OpenGL works fine...

OpenGL, Access violation


c++,opengl,access-violation
I am making an OpenGL project in Visual Studio 2010. I am following a tutorial from youtube. I don't know where the error is, and I have this error: Unhandled exception at 0x00000000 in OpenGL First Game.exe: 0xC0000005: Access violation. Main.cpp #include <GL/glew.h> #include <iostream> #include <GL/glut.h> #include "Sprite.h" Sprite...

Java: FloatBuffer to OpenGL - wrap() vs. allocate() vs. BufferUtils.createBuffer()


java,opengl,buffer
Datasource: float[] v = { ... }; Working example: FloatBuffer buf = BufferUtils.createFloatBuffer(v.length); buf.put(v); buf.flip(); // or buf.rewind() The buffer can now be uploaded to opengl and works fine: ... glBufferData(..., buf, ...); ... Why do the following examples of the buffer creation not also work? Not working 1: FloatBuffer...

What is the difference between glUseProgram() and glUseShaderProgram()?


c++,c,opengl,shader
In OpenGL what is the difference between glUseProgram() and glUseShaderProgram()? It seems in MESA and Nvidia provided glext.h, and in GLEW, both are defined, and both seem to do basically the same thing. I find documentation for glUseProgram() but not for glUseShaderProgram(). Are they truly interchangeable?...

scale texture opengl 2


opengl,textures,scale
I have a rectangle in opengl 2 and I'm using a texture for it. It Works, but the texture is repeated over the rectangle, and what I want is to adapt to the size of the rectangle. I have read in this tutorial about the different parameters you can set...

Opengl - Is glDrawBuffers modification stored in a FBO? No?


opengl,state-machines,render-to-texture
I try to create a FrameBuffer with 2 textures attaching to it (Multi Render Targets). Then in every time step, both textures are cleared and painted, as following code. (Some part will be replaced as pseudo code to make it shorter.) Version 1 //beginning of the 1st time step initialize(framebufferID12)...

glDeleteRenderbuffersEXT via remote desktop


windows,opengl,remote-desktop
I have an application that uses OpenGL. If I connect to a computer via Windows Remote Desktop I get an exception "Extension function glDeleteRenderbuffersEXT not supported" from my application. I think the exception is caused because Remote Desktop does not support the extension. My plan is to detect if the...

Reading a shader from a .txt file using a structure


c++,opengl,struct,shader
I've started learning how to use OpenGL and I absolutely hate having my shaders declared as global variables before my main(). I thought it would be cool to make a structure or class that would read the shader from a file in my project directory. The file reading works perfectly...

Need Minimum Textures required for OpenGL


opengl
Quick question, what is the minimum amount of textures that can be bound for the fragment shader that a OpenGL implementation is required to have? Note: I would like to know this for OpenGL 1.5, for OpenGL 2.0, and OpenGL 2.1...

OpenGL - translation stretches and distorts sprite


c++,opengl,transform,translation,distortion
I am loosely following the very handy tutorial at opengl-tutorial.org. I've been able to create a mesh, draw a sprite to it, and rotate and scale that mesh perfectly fine. However, I'm running into some issues when trying to translate the mesh. (pictures below) Here's an update function on the...

wxWidgets with AUI: OpenGL render loop method and wxPaintEvent


c++,user-interface,opengl,wxwidgets
The method I traditionally use of drawing to an OpenGL canvas with wxWidgets is to trigger a 30 hertz timed refresh() from the current OpenGL canvas, which then generates a "wxEVT_PAINT", which I can propogate out to the rest of the frame. I also bind to the wxEVT_PAINT and call...

glclearcolor best color?


opengl,optimization
this might seam like a stupid question but i was wondering, when calling glClear(GL11.GL_COLOR_BUFFER_BIT); glClearColor(1, 0, 0, 1); to clear the screen in my opengl project is there any performance differences for using different colors? i mean if for example i clear to red vs blue/green/*insert any color will it...

Spotlight with shadows becomes square-like


c++,opengl,graphics,shader,shadow
I've been following a two part tutorial on shadow mapping from OGLDev (part 1, part 2) for a couple of days now, and I've nearly finished implementing it. My problem is that when I enable shadow maps the illuminated region which shadows appear in appears as a "strip" and I'm...

How to create latitudinal (horizontal) contour lines in GLSL?


opengl,glsl,webgl
I'm aiming for this effect: (horizontal-only contour lines): I did find this example, however it creates horizontal and vertical contour lines. I can't quite wrap my head around how the call to fwidth() is generating the lines. uniform float gsize;//size of the grid uniform float gwidth;//grid lines'width in pixels varying...

OpenGL glTexImage2D memory issue


c,opengl
I'm loading a cubemap to create a skybox, everything is fine and the skybox renders properly with a correct texture application. However, I decided to check my program safety with valgrind, Valgrind gives this error: http://pastebin.com/seqmXjyx The line 53 in sky.c is: glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, texture.width, texture.height, 0,...

OpenGL: try to draw lines using VBO(vertex buffer object), it doesn't display


c,opengl,vbo,vertex-buffer-objects
I try to switch my openGL code from using display list to using VBO. In the code, I tried to draw a green-grid floor, which is composed by green lines in parallel with x-axis and green lines in parallel with z-axis. But when the program runs, floor doesn't display. And...

Need help finding out why the texture doesn't load


java,opengl
Trying to find a way to render a simple 2D image in Java using OpenGL I stumbled upon a more or less understandable class that does all of the image loading for you which I could not understand how to do. I believe it belongs to a person named Krythic...

Qt OpenGL transform feedback buffer functions missing


c++,qt,opengl,transform-feedback
I've been following a tutorial series for learning OpenGL, and the current tutorial I'm trying to do involves creating particle systems using the OpenGL transform feedback buffer. In my application I've been using Qt version 5.4.2 for simple 2D interface design, as well as for 3D rendering since it seems...

Passing an int to a function, then using that int to create an array


c++,arrays,opengl
I'm trying to create a textureLoader class for my openGL project and I can't initialize an array of textures inside of my class constructor because the the array won't accept anything unless it's a const int. To paint you a simple picture... myFunction(NUM) { GLuint textures[NUM]; } My past Failures...

Haskell - Could not deduce … from Context error - OpenGL AsUniform class type


class,haskell,opengl,types,uniform
I'm working on making my data types general instead of taking in the OpenGL type GLfloat. So I started making it take in type a and then just replacing everything with that. Now, I've come to a point where I'm setting uniform variables, but they take in GLfloat's. I'm using...

How can I render an infinite 2D grid in GLSL?


opengl,glsl
Ideally, what I'd like to do is draw a single quad and have GLSL handle the creation of the actual gridlines. In my attempt so far the vertex shader: #version 400 layout (location = 0) in vec4 in_position; layout (location = 2) in vec3 in_UV; uniform mat4 model; uniform mat4...

OpenGL program works only in Debug mode in Visual Studio 2013


c++,opengl,visual-studio-2013,release
my small OpenGL application works fine in Debug mode, but if I build it in Release mode I often get this error: Shader Creation Error: - Vertex shader failed to compile with the following errors: ERROR: 0:22: error(#132) Syntax error: "]" parse error ERROR: error(#273) 1 compilation errors. No code...

Is it possible to build a heatmap from point data at 60 times per second?


c++,opengl,visualization,simulation,heatmap
I'm working on a simulation for clouds (actual clouds) where the clouds are simulated by 3D points, then projected into a 2D heatmap, about 640x480 units big. The number of points is about 50k, which is as small as I can go without the simulation breaking, but I can't seem...

OpenGL: Defining variables in shaders


opengl,glsl
My OpenGL program, using GLSL for shaders, has a simple vertex and fragment shader (given by a tutorial). The vertex shader is: #version 330 layout (location = 0) in vec3 Position; void main() { gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0); } And the fragment shader is:...

Win32 Message Pump and std::thread Used to Create OpenGL Context and Render


multithreading,winapi,opengl,c++11
If I have a function that does the following: bool foo::init() { [Code that creates window] std::thread run(std::bind(&foo::run, this)); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } Where run is defined as: void foo::run() { [Code that creates initial opengl context] [Code that recreates window based on new...

Creating GUI with OpenGL


java,opengl
I am trying to write a Java programm using LWJGL 3 and so far I've made it to creating a window, rendering to it and getting basic input. But I've ran into a problem with creating GUI and namely text fields that my programm requires. I found information that there...

How to update the “forward” movement in OpenGL


c++,opengl,camera,fps
I have a problem with my OpenGL application that you can clearly see in this gif. Basically I would like to move in the direction pointed by the cursor, but this doesn't happen and instead the "forward" direction remains the same. For example if I turn 180° and press "w"...

What OpenGL loading library to use? [closed]


c++,opengl
Does anybody know an OpenGL loading library similar go GLEW that loads functions for OpenGL 2.0 but DOES NOT define them as macros?

Can the OpenGL 'deprecated' functions possibly be unsupported?


c++,c,opengl,graphics,deprecated
I am testing with glDrawPixels to port my simple pixel-drawn 2D game from Windows API to OpenGL with GLFW. It runs nicely with FPS over 100, additionally cross-platform. Just one thing that is slightly annoying me is that I'm using a deprecated feature. I don't see any problems now, but...

R32I sampler2D returns always 0


c++,opengl
I have a (default vertex and) fragment shader that should resize textures and scale their color by a specific factor for brightness correction. The result is rendered into an GL_UNSIGNED_INT_8_8_8_8 framebuffer. #version 330 uniform sampler2D tex; uniform vec2 screenSize; uniform float scale; layout(location = 0) out vec4 color; void main()...

OpenGL4: Rotation looks all wrong


c++,opengl,glm-math
Here's the vertex buffer information of the quad I'm drawing: static const GLfloat pv_quad[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, }; This quad is used to draw 2D frames on the screen as part of the graphical user interface. The class I...

C++ Opengl - How to load tgas and pngs in modern OpenGL? [on hold]


image,opengl,c++11,png,tga
I am looking for a way to load tgas and pngs in C++ Opengl - I dislike the idea of using a library though. Is there any sample code / links / advice you could give me in this topic?...

OpenGL: Strange bahaviour of VBO deletion?


c++,opengl,vbo,opengl-3,vao
I am getting a strange issue in Vertex Buffer Object (VBO). I created a class that includes VBO creation and deletion. I delete all the VBOs (with glDeleteBuffers()) in the destructor of the class. Now I created 2 OpenGL context windows each running with VBO class. Now when I close...

Why normal mapping doesn't appear correctly?


opengl,jogl
I'm applying bump mapping to a tree. When no normal mapping applied, it appears like this. But when a normal texture is used, it turned out to be too aggressive as follow which is ugly. I checked tangent data which should be fine. So I was wondering if it's because...

OpenGL: GL_FRAMEBUFFER_UNSUPPORTED on specific combinations of framebuffer attachments


c++,opengl,textures,nvidia,framebuffer
Im trying to attach multiple targets to a framebuffer object. I have the following problem: There is no error, when using float texture attachments and a depth attachment. There is also no error, when using float texture attachments and integer texture attachments. Although these combinations work, I cant use float,...

Why are shaders and programs stored as integers in OpenGL?


c++,opengl,opengl-es,integer,shader
I'm following the "OpenGL Superbible" book and I can't help but notice that when we create a shader and create the program that we attach the shaders to, we store them as GLuint which are unsigned integers. Why are they stored as numbers? What does the value of the number...

GLFW3 create window returns null


c,opengl,struct,code-separation
I was trying to put all GLFW3 init code from main to separate file. When I'm running the code, I get EXC_BAD_ACCESS on glew init function, because GLFW could not create window. Before code separation everything was ok. Is it possible to have GLFW setup code in other function? I'm...

CheckMultisampleQualityLevels(…) says the card does not support MSAA (which is not true for e.g. my GeForce GTX 780)?


c++,directx,directx-11,msaa
I use CheckMultisampleQualityLevels(...) to establish the MSAA support on my hardware. I do it in that order: D3D11CreateDevice(...) gives me device device->CheckMultisampleQualityLevels(...) Pass results to DXGI_SWAP_CHAIN_DESC.SampleDesc CreateSwapChain(...) with given DXGI_SWAP_CHAIN_DESC The problem is, CheckMultisampleQualityLevels(...) always gives me 0 for pNumQualityLevels. And I'm sure that my graphic card supports some MSAA...

Multitexturing theory with texture objects and samplers


opengl,textures
I couldn't find any good theory articles on how to code multitexturing with either only texture objects or texture objects plus samplers. I just don't know how to manage the glActiveTexture function and what it exactly does. glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0 + 0); // Number between 0 and GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS glBindTexture(GL_TEXTURE_2D, texture);...

OpenGL: Using glColorPointer make color weird


opengl
Like the picture showed in the link below. I want to color my robot hand with white color(RGB: 0.9 0.9 0.9). When I use glColor3f, the white color display correctly. But when I store RGB data in GLfloat array and call glColorPointer, the color becomes so weird. Here is code...

No OpenGL context is current in the current thread


java,opengl,lwjgl
I'm following a tutorial on youtube but I have a problem with OpenGL that I'm not able to solve. I have no idea how I can fix it. Exception in thread "EndlessRunner" java.lang.IllegalStateException: No OpenGL context is current in the current thread. at org.lwjgl.opengl.GLContextWindows.createFromCurrent(GLContextWindows.java:61) at org.lwjgl.opengl.GLContext.createFromCurrent(GLContext.java:36) at net.alfredo.Main.init(Main.java:59) at net.alfredo.Main.run(Main.java:91)...