GLSL 固定功能片段程序替换 [英] GLSL fixed function fragment program replacement

查看:29
本文介绍了GLSL 固定功能片段程序替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用 OpenGL 固定函数管道进行顶点设置时,片段程序如何与固定函数顶点设置兼容?我想这通常取决于光源和纹理层等的数量.那么例如,一个简单的非纹理单光源 goraud 着色片段程序如何替代 GL 的固定功能着色器?

解决方案

虽然 Gouraud shading计算顶点着色器中的光,Phong shading 计算片段着色器中的光.

标准的 OpenGL 光照模型是一个 Gouraud shading 模型,带有 Blinn-Phong 光模型(不要与 Phong 阴影).

标准的 OpenGL Blinn-Phong 光模型计算如下这个:

Ka ...环境材料Kd ... 扩散材料Ks ... 镜面材质La ...环境光Ld ...漫射光Ls ... 镜面光sh ... 闪亮N ... 正常向量L ... 光向量(从顶点位置到光)V ... 视图向量(从顶点位置到眼睛)Id = max(dot(N, L), 0.0);H = 归一化(V + L);NdotH = max(dot(N, H), 0.0);是 = (sh + 2.0) * pow(NdotH, sh)/(2.0 * 3.14159265);fs = Ka*La + Id*Kd*Ld + Is*Ks*Ls;

以下函数计算单个定向 Blinn-Phong 光源:

struct TLightSource{vec3 lightDir;vec3 环境;vec3 漫反射;vec3 镜面;漂浮光泽;};统一 TLightSource u_lightSource;vec3 Light( vec3 eyeV, vec3 N ){vec3 lightCol = u_lightSource.ambient;vec3 L = 标准化(-u_lightSource.lightDir);浮点 NdotL = max( 0.0, dot( N, L ) );lightCol += NdotL * u_lightSource.diffuse;vec3 H = 归一化(eyeV + L);浮点 NdotH = max( 0.0, dot( N, H ) );浮动 kSpecular = ( u_lightSource.shininess + 2.0 ) * pow( NdotH, u_lightSource.shininess )/( 2.0 * 3.14159265 );lightCol += kSpecular * u_lightSource.specular;返回 lightCol;}

另请参阅以下问题的答案:

这个函数可以应用于顶点着色器,也可以应用于片段着色器.

gouraud 着色器程序和 phong 着色器程序的完整代码可以在以下 WebGL 示例中找到:

(function loadscene() {var resize, gl, gouraudDraw, phongDraw, vp_size;var bufCube, bufSphere, bufTorus;var 滑块刻度 = 100.0;函数渲染(delteMS){varambient_col = hexToRgb(document.getElementById("ambient_col").value);vardiffuse_col = hexToRgb(document.getElementById("diffuse_col").value);var specular_col = hexToRgb( document.getElementById( "specular_col" ).value );var 环境 = document.getElementById( "ambient" ).value/sliderScale;vardiffuse = document.getElementById("diffuse").value/sliderScale;var specular = document.getElementById( "specular" ).value/sliderScale;var shininess = document.getElementById( "shininess" ).value;varambientCol = [ambient_col.r*ambient/256.0,ambient_col.g*ambient/256.0,ambient_col.b*ambient/256.0];vardiffuseCol = [diffuse_col.r*diffuse/256.0,diffuse_col.g*diffuse/256.0,diffuse_col.b*diffuse/256.0];var specularCol = [specular_col.r*ambient/256.0,specular_col.g*ambient/256.0,specular_col.b*ambient/256.0];var form = document.getElementById( "form" ).value;var shading = document.getElementById( "shading" ).value;相机创建();Camera.vp = vp_size;gl.enable(gl.DEPTH_TEST);gl.clearColor( 0.0, 0.0, 0.0, 1.0 );gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );gl.启用(gl.CULL_FACE);gl.cullFace(gl.BACK);//gl.frontFace(gl.CW);gl.frontFace(gl.CCW);var progDraw = shading == 0 ?gouraudDraw : phongDraw;;//设置绘制着色器ShaderProgram.Use( progDraw.prog );ShaderProgram.SetUniformM44( progDraw.prog, "u_projectionMat44", Camera.Perspective());ShaderProgram.SetUniformM44( progDraw.prog, "u_viewMat44", Camera.LookAt());ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.lightDir", [-1.0, -0.5, -2.0] )ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.ambient",ambientCol)ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.diffuse",diffuseCol)ShaderProgram.SetUniformF3( progDraw.prog, "u_lightSource.specular", specularCol )ShaderProgram.SetUniformF1( progDraw.prog, "u_lightSource.shininess", shininess )var modelMat = IdentityMat44()modelMat = RotateAxis(modelMat, CalcAng(delteMS, 13.0), 0);modelMat = RotateAxis(modelMat, CalcAng(delteMS, 17.0), 1);ShaderProgram.SetUniformM44( progDraw.prog, "u_modelMat44", modelMat );//绘制场景bufObj = 表单 == 0 ?bufCube:形式==1?bufSphere : bufTorus;VertexBuffer.Draw( bufObj );请求动画帧(渲染);}函数调整大小(){//vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];vp_size = [window.innerWidth, window.innerHeight]canvas.width = vp_size[0];canvas.height = vp_size[1];gl.viewport(0, 0, vp_size[0], vp_size[1]);}函数 initScene() {document.getElementById( "ambient_col" ).value = "#FFFFFF";document.getElementById( "diffuse_col" ).value = "#FFFFFF";document.getElementById( "specular_col" ).value = "#FFFFFF";document.getElementById( "ambient" ).value = 0.2 * sliderScale;document.getElementById( "diffuse" ).value = 0.6 * sliderScale;document.getElementById( "specular" ).value = 0.8 * sliderScale;document.getElementById( "shininess" ).value = 25.0;document.getElementById( "shading" ).value = 0;document.getElementById( "form" ).value = 1;canvas = document.getElementById("canvas");gl = canvas.getContext( "experimental-webgl" );如果(!gl)返回空;gouraudDraw = {}gouraudDraw.prog = ShaderProgram.Create([ { 来源:gouraud-shader-vs",舞台:gl.VERTEX_SHADER },{ 来源:gouraud-shader-fs",舞台:gl.FRAGMENT_SHADER }],[ "u_projectionMat44", "u_viewMat44", "u_modelMat44","u_lightSource.lightDir", "u_lightSource.ambient", "u_lightSource.diffuse", "u_lightSource.specular", "u_lightSource.shininess", ] );如果( gouraudDraw.prog == 0 )返回;gouraudDraw.inPos = gl.getAttribLocation( gouraudDraw.prog, "inPos" );gouraudDraw.inNV = gl.getAttribLocation( gouraudDraw.prog, "inNV" );gouraudDraw.inCol = gl.getAttribLocation( gouraudDraw.prog, "inCol" );phongDraw = {}phongDraw.prog = ShaderProgram.Create([ { 来源:phong-shader-vs",阶段:gl.VERTEX_SHADER },{ 来源:phong-shader-fs",阶段:gl.FRAGMENT_SHADER }],[ "u_projectionMat44", "u_viewMat44", "u_modelMat44","u_lightSource.lightDir", "u_lightSource.ambient", "u_lightSource.diffuse", "u_lightSource.specular", "u_lightSource.shininess", ] );如果( phongDraw.prog == 0 )返回;phongDraw.inPos = gl.getAttribLocation( phongDraw.prog, "inPos" );phongDraw.inNV = gl.getAttribLocation( phongDraw.prog, "inNV" );phongDraw.inCol = gl.getAttribLocation( phongDraw.prog, "inCol" );//创建立方体var cubePos = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0 ];var cubeCol = [ 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ];var cubeHlpInx = [ 0, 1, 2, 3, 1, 5, 6, 2, 5, 4, 7, 6, 4, 0, 3, 7, 3, 2, 6, 7, 1, 0, 4,5];var cubePosData = [];for ( var i = 0; i = 0) ?0 : Math.sqrt( -a_b );返回 [ a * Math.sin( angRag ) - ea, b * Math.cos( angRag ) - eb, 0 ];}glArrayType = typeof Float32Array !="undefined" ?Float32Array : ( typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array );功能 IdentityMat44() {var m = new glArrayType(16);米[0] = 1;m[1] = 0;m[2] = 0;m[3] = 0;m[4] = 0;米[5] = 1;米[6] = 0;米[7] = 0;米[8] = 0;米[9] = 0;米[10] = 1;米[11] = 0;米[12] = 0;m[13] = 0;m[14] = 0;米[15] = 1;返回 m;};函数旋转轴(matA,angRad,轴){var aMap = [ [1, 2], [2, 0], [0, 1] ];var a0 = aMap[axis][0], a1 = aMap[axis][1];var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);var matB = new glArrayType(16);for ( var i = 0; i <16; ++ i ) matB[i] = matA[i];for ( var i = 0; i <3; ++ i ) {matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;}返回 matB;}function Cross( a, b ) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],a[0] * b[1] - a[1] * b[0], 0.0 ];}function Dot( a, b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];}函数归一化( v ) {var len = Math.sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );返回 [ v[0]/len, v[1]/len, v[2]/len ];}var 相机 = {};Camera.create = function() {this.pos = [0, 3, 0.0];this.target = [0, 0, 0];this.up = [0, 0, 1];this.fov_y = 90;this.vp = [800, 600];this.near = 0.5;this.far = 100.0;}Camera.Perspective = function() {var fn = this.far + this.near;var f_n = this.far - this.near;var r = this.vp[0]/this.vp[1];var t = 1/Math.tan( Math.PI * this.fov_y/360 );var m = IdentityMat44();m[0] = t/r;m[1] = 0;m[2] = 0;m[3] = 0;m[4] = 0;m[5] = t;米[6] = 0;米[7] = 0;米[8] = 0;米[9] = 0;m[10] = -fn/f_n;m[11] = -1;米[12] = 0;m[13] = 0;m[14] = -2 * this.far * this.near/f_n;米[15] = 0;返回 m;}Camera.LookAt = 函数(){var mz = Normalize( [ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ] );var mx = Normalize( Cross( this.up, mz ) );var my = Normalize( Cross( mz, mx ) );var tx = Dot( mx, this.pos );var ty = Dot( my, this.pos );var tz = Dot( [-mz[0], -mz[1], -mz[2]], this.pos );var m = IdentityMat44();m[0] = mx[0];米[1] = 我的[0];m[2] = mz[0];m[3] = 0;m[4] = mx[1];米[5] = 我的[1];m[6] = mz[1];米[7] = 0;m[8] = mx[2];米[9] = 我的[2];m[10] = mz[2];米[11] = 0;m[12] = tx;m[13] = ty;m[14] = tz;米[15] = 1;返回 m;}var ShaderProgram = {};ShaderProgram.Create = 函数(着色器列表){var shaderObjs = [];for ( var i_sh = 0; i_sh < shaderList.length; ++ i_sh ) {var shderObj = this.CompileShader( shaderList[i_sh].source, shaderList[i_sh].stage);如果(shderObj == 0)返回0;shaderObjs.push( shderObj );}var progObj = this.LinkProgram( shaderObjs )如果(progObj != 0){progObj.attribIndex = {};var noOfAttributes = gl.getProgramParameter( progObj, gl.ACTIVE_ATTRIBUTES );for ( var i_n = 0; i_n