• glsl实现像素光照的方法


    GLSL Tutorial


    Directional Light per Pixel


    In this section we'll modify the previous shaders to compute the directional light per pixel. Basically we're going to split the work between the two shaders, so that some operations are done per pixel.

    First lets take a look at the information we receive per vertex:
    //我们可以从每个顶点接收三个数值

    • normal //顶点法向量
    • half vector //眼睛坐标和灯光的方向的和
    • light direction //灯光的方向
    We have to transform the normal to eye space, and normalize it. We also have to normalize both the half vector and the light direction, both of which are already in eye space. These normalized vectors are to be interpolated and then sent to the fragment shader so we need to declare varying variables to hold the normalized vectors.

    We can also perform some computations combining the lights settings with the materials in the vertex shader, hence helping to split the load between the vertex and fragment shader.

    The vertex shader could be:


    	varying vec4 diffuse,ambient;
    	varying vec3 normal,lightDir,halfVector;
    	
    	void main()
    	{	
    		/* first transform the normal into eye space and 
    		normalize the result */
    		normal = normalize(gl_NormalMatrix * gl_Normal);
    		
    		/* now normalize the light's direction. Note that 
    		according to the OpenGL specification, the light 
    		is stored in eye space. Also since we're talking about 
    		a directional light, the position field is actually direction */
    		lightDir = normalize(vec3(gl_LightSource[0].position));
    	        //gl_LightSource[0].position存储在眼坐标
    		/* Normalize the halfVector to pass it to the fragment shader */
    		halfVector = normalize(gl_LightSource[0].halfVector.xyz);
                    //把halfVector传递给片元着色器
    					
    		/* Compute the diffuse, ambient and globalAmbient terms */
    		diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
    		ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
    		ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;//全局环境光
    	
    		gl_Position = ftransform();
    	} 
    

    Now for the fragment shader. The same varying variables have to be declared. We have to normalize again the normal. Note that there is no need to normalize again the light direction. This last vector is common to all vertices since we're talking about a directional light. The interpolation between two equal vectors yields the same vector, so there is no need to normalize again. Then we compute the dot product between the interpolated normalized normal and the light direction.


    	varying vec4 diffuse,ambient;
    	varying vec3 normal,lightDir,halfVector;
    	
    	
    	void main()
    	{
    		vec3 n,halfV;
    		float NdotL,NdotHV;
    		
    		/* The ambient term will always be present */
    		vec4 color = ambient;
    		
    		/* a fragment shader can't write a varying variable, hence we need
    		a new variable to store the normalized interpolated normal */
    		n = normalize(normal);
    		
    		/* compute the dot product between normal and ldir */
    		NdotL = max(dot(n,lightDir),0.0);
    	
    		....
    	}
    

    If the dot product NdotL is greater than zero then we must compute the diffuse component, which is the diffuse setting we received from the vertex shader multiplied by the dot product. We must also compute the specular term. To compute the specular component we must first normalize the halfvector we received from the vertex shader, and also compute the dot product between the normalized halfvector and the normal.


    		...
    		if (NdotL > 0.0) {
    			color += diffuse * NdotL;
    			halfV = normalize(halfVector);
    			NdotHV = max(dot(n,halfV),0.0);
    			color += gl_FrontMaterial.specular * 
    					gl_LightSource[0].specular * 
    					pow(NdotHV, gl_FrontMaterial.shininess);
    		}
    	
    		gl_FragColor = color;
    }
    

    The following images show the difference in terms of visual results between computing the lighting per vertex versus per pixel.

    Per Vertex Per Pixel

    A Shader Designer project containing the shaders for the directional light per pixel can be found in here

  • 相关阅读:
    《更好的解释(数学篇)》——第一章
    流密码及RC4算法ZZ
    Android
    Android中Handler 、Thread和Runnable之间的关系ZZ
    Android之Handler消息传递机制详解zz
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之四(三十)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之三(二十九)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之二(二十八)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之一(二十七)
    abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理八(二十六)
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/1544005.html
Copyright © 2020-2023  润新知