2011-11-17 49 views
37

Tôi đang viết một ứng dụng 3D cho iOS. Tôi mới sử dụng OpenGL ES 2.0, vì vậy tôi vẫn tiếp tục viết các trình đổ bóng cơ bản. Tôi thực sự cần phải thực hiện một hiệu ứng "Glow" trên một số mô hình của tôi, dựa trên kết cấu.Làm cách nào để có hiệu ứng đổ bóng "Glow" trong OpenGL ES 2.0?

Đây là mẫu:

Bloom/Glow from www.skillmanmedia.com/realbasic/bloomsnapshot.jpg .

Tôi đang tìm các ví dụ mã cho OpenGL ES 2.0. Hầu hết mã tôi tìm thấy trên internet là cho OpenGL hoặc D3D trên máy tính để bàn.

Bất kỳ ý tưởng nào?

+5

Hiệu ứng đổ bóng khác nhau rất ít giữa opengl ES 2.0 và màn hình nền. Nếu bạn tìm thấy một hướng dẫn tốt làm những gì bạn muốn, chuyển nó sẽ là tầm thường. – NickLH

+0

Cảm ơn sự bảo đảm, đó là một điều khác đang làm phiền tôi. Một số ví dụ (thường là cũ) sử dụng các biến đầu vào/đầu ra, mà tôi không thể tìm thấy trong tài liệu ES. Tôi sẽ tiếp tục đào bới, nhưng bất kỳ ví dụ hay nào cũng thường là một bước nhảy vọt trong nghiên cứu của tôi và hiểu biết về cách sử dụng GLSL. –

+0

Có ai có mã Android nào không? – Burf2000

Trả lời

1

Trang web GLSL Sandbox có bộ sưu tập các ví dụ đổ bóng. This one has the glow and appears to be able to compile for ES.

Bạn sẽ có thể sửa đổi chúng để kéo uv từ kết cấu của bạn.

Đây là some code directly from this site:

#ifdef GL_ES 
precision mediump float; 
#endif 

#extension GL_OES_standard_derivatives : enable 

uniform float time; 
uniform vec2 mouse; 
uniform vec2 resolution; 

void main(void){ 

    vec2 p = (gl_FragCoord.xy * 2.0 - resolution)/min(resolution.x, resolution.y); 
    vec3 color1 = vec3(0.0, 0.3, 0.5); 
    vec3 color2 = vec3(0.5, 0.0, 0.3); 

    float f = 0.0; 
    float g = 0.0; 
    float h = 0.0; 
    float PI = 3.14159265; 
    for(float i = 0.0; i < 40.0; i++){ 
     if (floor(mouse.x * 41.0) < i) 
      break; 
     float s = sin(time + i * PI/20.0) * 0.8; 
     float c = cos(time + i * PI/20.0) * 0.8; 
     float d = abs(p.x + c); 
     float e = abs(p.y + s); 
     f += 0.001/d; 
     g += 0.001/e; 
     h += 0.00003/(d * e); 
    } 


    gl_FragColor = vec4(f * color1 + g * color2 + vec3(h), 1.0); 
} 
2

Trước hết có tấn của các thuật toán và kỹ thuật để tạo ra một hiệu ứng ánh sáng. Tôi chỉ muốn trình bày một khả năng.

Trước tiên, bạn nên tạo một Chất liệu tự phát sáng. Đối với điều này tôi sử dụng một mô hình ánh sáng blinn-phong sửa đổi, trong đó hướng đến nguồn ánh sáng luôn luôn là hướng ngược của vectơ bình thường của đoạn.

varying vec3 vertPos; 
varying vec3 vertNV; 
varying vec3 vertCol; 

void main() 
{ 
    vec3 color = vertCol; 

    float shininess = 10.0; 
    vec3 normalV = normalize(vertNV); 
    vec3 eyeV = normalize(-vertPos); 
    vec3 halfV = normalize(eyeV + normalV); 
    float NdotH = max(0.0, dot(normalV, halfV)); 
    float glowFac = (shininess + 2.0) * pow(NdotH, shininess)/(2.0 * 3.14159265); 

    gl_FragColor = vec4(color.rgb * (0.5 + glowFac), 1.0); 
} 

Trong bước thứ hai, thuật toán gaussian blur được thực hiện trên đầu ra. Khung cảnh được ghi vào bộ đệm khung với một kết cấu gắn với mặt phẳng màu. Một không gian màn hình vượt qua sử dụng kết cấu làm đầu vào để làm mờ đầu ra.
Vì lý do hiệu suất, thuật toán mờ được thực hiện đầu tiên dọc theo trục X của chế độ xem và trong bước tiếp theo dọc theo trục Y của chế độ xem.
Mô tả chi tiết thuật toán mờ có thể tìm thấy tại câu trả lời cho câu hỏi OpenGL es 2.0 Gaussian blur on triangle.

varying vec2 vertPos; 
uniform sampler2D u_textureCol; 
uniform vec2 u_textureSize; 
uniform float u_sigma; 
uniform int u_width; 

float CalcGauss(float x, float sigma) 
{ 
    float coeff = 1.0/(2.0 * 3.14157 * sigma); 
    float expon = -(x*x)/(2.0 * sigma); 
    return (coeff*exp(expon)); 
} 

void main() 
{ 
    vec2 texC = vertPos.st * 0.5 + 0.5; 
    vec4 texCol = texture(u_textureCol, texC); 
    vec4 gaussCol = vec4(texCol.rgb, 1.0); 
    vec2 step = 1.0/u_textureSize; 
    for (int i = 1; i <= u_width; ++ i) 
    { 
     vec2 actStep = vec2(float(i) * step.x, 0.0); // this is for the X-axis 
     // vec2 actStep = vec2(0.0, float(i) * step.y); this would be for the Y-axis 

     float weight = CalcGauss(float(i)/float(u_width), u_sigma); 
     texCol = texture2D(u_textureCol, texC + actStep);  
     gaussCol += vec4(texCol.rgb * weight, weight); 
     texCol = texture2D(u_textureCol, texC - actStep); 
     gaussCol += vec4(texCol.rgb * weight, weight); 
    } 
    gaussCol.rgb /= gaussCol.w; 
    gl_FragColor = vec4(gaussCol.rgb, 1.0); 
} 

Xem thêm câu trả lời cho những câu dưới đây:

Xem theo gương WebGL tương tự mà đặt tất cả với nhau:

var readInput = true; 
 
function changeEventHandler(event){ 
 
    readInput = true; 
 
} 
 
    
 
(function loadscene() { 
 
    
 
    var resize, gl, progDraw, progBlurX, progPost, vp_size, blurFB; 
 
    var bufCube = {}; 
 
    var bufQuad = {}; 
 
    var shininess = 10.0; 
 
    var glow = 10.0; 
 
    var sigma = 0.8; 
 
    
 
    function render(delteMS){ 
 

 
     if (readInput) { 
 
      readInput = false; 
 
      var sliderScale = 100; 
 
      shininess = document.getElementById("shine").value; 
 
      glow  = document.getElementById("glow").value/sliderScale; 
 
      sigma  = document.getElementById("sigma").value/sliderScale; 
 
     } 
 

 
     Camera.create(); 
 
     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); 
 

 
     // set up framebuffer 
 
     gl.bindFramebuffer(gl.FRAMEBUFFER, blurFB[0]); 
 
     gl.viewport(0, 0, blurFB[0].width, blurFB[0].height); 
 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
    
 
     // set up draw shader 
 
     ShaderProgram.Use(progDraw.prog); 
 
     ShaderProgram.SetUniformM44(progDraw.prog, "u_projectionMat44", Camera.Perspective()); 
 
     ShaderProgram.SetUniformM44(progDraw.prog, "u_viewMat44", Camera.LookAt()); 
 
     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); 
 
     ShaderProgram.SetUniformF1(progDraw.prog, "u_shininess", shininess); 
 
     ShaderProgram.SetUniformF1(progDraw.prog, "u_glow", glow); 
 
     
 
     // draw scene 
 
     VertexBuffer.Draw(bufCube); 
 

 
     // set blur-X framebuffer and bind frambuffer texture 
 
     gl.bindFramebuffer(gl.FRAMEBUFFER, blurFB[1]); 
 
     gl.viewport(0, 0, blurFB[1].width, blurFB[1].height); 
 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
     var texUnit = 1; 
 
     gl.activeTexture(gl.TEXTURE0 + texUnit); 
 
     gl.bindTexture(gl.TEXTURE_2D, blurFB[0].color0_texture); 
 

 
     // set up blur-X shader 
 
     ShaderProgram.Use(progBlurX.prog); 
 
     ShaderProgram.SetUniformI1(progBlurX.prog , "u_texture", texUnit) 
 
     ShaderProgram.SetUniformF2(progBlurX.prog , "u_textureSize", vp_size); 
 
     ShaderProgram.SetUniformF1(progBlurX.prog , "u_sigma", sigma) 
 

 
     // draw full screen space 
 
     gl.enableVertexAttribArray(progBlurX.inPos); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos); 
 
     gl.vertexAttribPointer(progBlurX.inPos, 2, gl.FLOAT, false, 0, 0); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx); 
 
     gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 
 
     gl.disableVertexAttribArray(progBlurX.inPos); 
 

 
     // reset framebuffer and bind frambuffer texture 
 
     gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
     gl.viewport(0, 0, vp_size[0], vp_size[1]); 
 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
     texUnit = 2; 
 
     gl.activeTexture(gl.TEXTURE0 + texUnit); 
 
     gl.bindTexture(gl.TEXTURE_2D, blurFB[1].color0_texture); 
 

 
     // set up pst process shader 
 
     ShaderProgram.Use(progPost.prog); 
 
     ShaderProgram.SetUniformI1(progPost.prog, "u_texture", texUnit) 
 
     ShaderProgram.SetUniformF2(progPost.prog, "u_textureSize", vp_size); 
 
     ShaderProgram.SetUniformF1(progPost.prog, "u_sigma", sigma); 
 

 
     // draw full screen space 
 
     gl.enableVertexAttribArray(progPost.inPos); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos); 
 
     gl.vertexAttribPointer(progPost.inPos, 2, gl.FLOAT, false, 0, 0); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx); 
 
     gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 
 
     gl.disableVertexAttribArray(progPost.inPos); 
 

 
     requestAnimationFrame(render); 
 
    } 
 
    
 
    function resize() { 
 
     //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight]; 
 
     vp_size = [window.innerWidth, window.innerHeight] 
 
     canvas.width = vp_size[0]; 
 
     canvas.height = vp_size[1]; 
 

 
     var fbsize = Math.max(vp_size[0], vp_size[1])-1; 
 
     fbsize = 1 << 31 - Math.clz32(fbsize); // nearest power of 2 
 
     fbsize = fbsize * 2 
 

 
     blurFB = []; 
 
     for (var i = 0; i < 2; ++ i) { 
 
      fb = gl.createFramebuffer(); 
 
      fb.width = fbsize; 
 
      fb.height = fbsize; 
 
      gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 
 
      fb.color0_texture = gl.createTexture(); 
 
      gl.bindTexture(gl.TEXTURE_2D, fb.color0_texture); 
 
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
 
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
 
      fb.renderbuffer = gl.createRenderbuffer(); 
 
      gl.bindRenderbuffer(gl.RENDERBUFFER, fb.renderbuffer); 
 
      gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height); 
 
      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fb.color0_texture, 0); 
 
      gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fb.renderbuffer); 
 
      gl.bindTexture(gl.TEXTURE_2D, null); 
 
      gl.bindRenderbuffer(gl.RENDERBUFFER, null); 
 
      gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
      blurFB.push(fb); 
 
     } 
 
    } 
 
    
 
    function initScene() { 
 
    
 
     canvas = document.getElementById("canvas"); 
 
     gl = canvas.getContext("experimental-webgl"); 
 
     if (!gl) 
 
     return null; 
 
    
 
     progDraw = {} 
 
     progDraw.prog = ShaderProgram.Create( 
 
     [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER }, 
 
      { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER } 
 
     ]); 
 
     if (!progDraw.prog) 
 
      return null; 
 
     progDraw.inPos = gl.getAttribLocation(progDraw.prog, "inPos"); 
 
     progDraw.inNV = gl.getAttribLocation(progDraw.prog, "inNV"); 
 
     progDraw.inCol = gl.getAttribLocation(progDraw.prog, "inCol"); 
 

 
     progBlurX = {} 
 
     progBlurX.prog = ShaderProgram.Create( 
 
     [ { source : "post-shader-vs", stage : gl.VERTEX_SHADER }, 
 
      { source : "blurX-shader-fs", stage : gl.FRAGMENT_SHADER } 
 
     ]); 
 
     progBlurX.inPos = gl.getAttribLocation(progBlurX.prog, "inPos"); 
 
     if (!progBlurX.prog) 
 
      return;  
 

 
     progPost = {} 
 
     progPost.prog = ShaderProgram.Create( 
 
     [ { source : "post-shader-vs", stage : gl.VERTEX_SHADER }, 
 
      { source : "blurY-shader-fs", stage : gl.FRAGMENT_SHADER } 
 
     ]); 
 
     progPost.inPos = gl.getAttribLocation(progPost.prog, "inPos"); 
 
     if (!progPost.prog) 
 
      return; 
 
     
 
     // create cube 
 
     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 < cubeHlpInx.length; ++ i) { 
 
     cubePosData.push(cubePos[cubeHlpInx[i]*3], cubePos[cubeHlpInx[i]*3+1], cubePos[cubeHlpInx[i]*3+2]); 
 
     } 
 
     var cubeNVData = []; 
 
     for (var i1 = 0; i1 < cubeHlpInx.length; i1 += 4) { 
 
     var nv = [0, 0, 0]; 
 
     for (i2 = 0; i2 < 4; ++ i2) { 
 
      var i = i1 + i2; 
 
      nv[0] += cubePosData[i*3]; nv[1] += cubePosData[i*3+1]; nv[2] += cubePosData[i*3+2]; 
 
     } 
 
     for (i2 = 0; i2 < 4; ++ i2) 
 
     cubeNVData.push(nv[0], nv[1], nv[2]); 
 
     } 
 
     var cubeColData = []; 
 
     for (var is = 0; is < 6; ++ is) { 
 
     for (var ip = 0; ip < 4; ++ ip) { 
 
     cubeColData.push(cubeCol[is*3], cubeCol[is*3+1], cubeCol[is*3+2]); 
 
     } 
 
     } 
 
     var cubeInxData = []; 
 
     for (var i = 0; i < cubeHlpInx.length; i += 4) { 
 
     cubeInxData.push(i, i+1, i+2, i, i+2, i+3); 
 
     } 
 
     bufCube = VertexBuffer.Create(
 
     [ { data : cubePosData, attrSize : 3, attrLoc : progDraw.inPos }, 
 
     { data : cubeNVData, attrSize : 3, attrLoc : progDraw.inNV }, 
 
     { data : cubeColData, attrSize : 3, attrLoc : progDraw.inCol } ], 
 
     cubeInxData); 
 

 
     bufQuad.pos = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos); 
 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0 ]), gl.STATIC_DRAW); 
 
     bufQuad.inx = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx); 
 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2, 0, 2, 3 ]), gl.STATIC_DRAW); 
 
     
 
     window.onresize = resize; 
 
     resize(); 
 
     requestAnimationFrame(render); 
 
    } 
 
    
 
    function Fract(val) { 
 
     return val - Math.trunc(val); 
 
    } 
 
    function CalcAng(deltaTime, intervall) { 
 
     return Fract(deltaTime/(1000*intervall)) * 2.0 * Math.PI; 
 
    } 
 
    function CalcMove(deltaTime, intervall, range) { 
 
     var pos = self.Fract(deltaTime/(1000*intervall)) * 2.0 
 
     var pos = pos < 1.0 ? pos : (2.0-pos) 
 
     return range[0] + (range[1] - range[0]) * pos; 
 
    }  
 
    function EllipticalPosition(a, b, angRag) { 
 
     var a_b = a * a - b * b 
 
     var ea = (a_b <= 0) ? 0 : Math.sqrt(a_b); 
 
     var eb = (a_b >= 0) ? 0 : Math.sqrt(-a_b); 
 
     return [ a * Math.sin(angRag) - ea, b * Math.cos(angRag) - eb, 0 ]; 
 
    } 
 
    
 
    glArrayType = typeof Float32Array !="undefined" ? Float32Array : (typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array); 
 
    
 
    function IdentityMat44() { 
 
    var m = new glArrayType(16); 
 
    m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0; 
 
    m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0; 
 
    m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; 
 
    m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; 
 
    return m; 
 
    }; 
 
    
 
    function RotateAxis(matA, angRad, axis) { 
 
     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; 
 
     } 
 
     return 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]; } 
 
    function Normalize(v) { 
 
     var len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 
 
     return [ v[0]/len, v[1]/len, v[2]/len ]; 
 
    } 
 
    
 
    var Camera = {}; 
 
    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; m[6] = 0;        m[7] = 0; 
 
     m[8] = 0; m[9] = 0; m[10] = -fn/f_n;      m[11] = -1; 
 
     m[12] = 0; m[13] = 0; m[14] = -2 * this.far * this.near/f_n; m[15] = 0; 
 
     return m; 
 
    } 
 
    Camera.LookAt = function() { 
 
     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]; m[1] = my[0]; m[2] = mz[0]; m[3] = 0; 
 
     m[4] = mx[1]; m[5] = my[1]; m[6] = mz[1]; m[7] = 0; 
 
     m[8] = mx[2]; m[9] = my[2]; m[10] = mz[2]; m[11] = 0; 
 
     m[12] = tx; m[13] = ty; m[14] = tz; m[15] = 1; 
 
     return m; 
 
    } 
 
    
 
    var ShaderProgram = {}; 
 
    ShaderProgram.Create = function(shaderList) { 
 
     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); 
 
      if (shderObj == 0) 
 
       return 0; 
 
      shaderObjs.push(shderObj); 
 
     } 
 
     var progObj = this.LinkProgram(shaderObjs) 
 
     if (progObj != 0) { 
 
      progObj.attribIndex = {}; 
 
      var noOfAttributes = gl.getProgramParameter(progObj, gl.ACTIVE_ATTRIBUTES); 
 
      for (var i_n = 0; i_n < noOfAttributes; ++ i_n) { 
 
       var name = gl.getActiveAttrib(progObj, i_n).name; 
 
       progObj.attribIndex[name] = gl.getAttribLocation(progObj, name); 
 
      } 
 
      progObj.unifomLocation = {}; 
 
      var noOfUniforms = gl.getProgramParameter(progObj, gl.ACTIVE_UNIFORMS); 
 
      for (var i_n = 0; i_n < noOfUniforms; ++ i_n) { 
 
       var name = gl.getActiveUniform(progObj, i_n).name; 
 
       progObj.unifomLocation[name] = gl.getUniformLocation(progObj, name); 
 
      } 
 
     } 
 
     return progObj; 
 
    } 
 
    ShaderProgram.AttributeIndex = function(progObj, name) { return progObj.attribIndex[name]; } 
 
    ShaderProgram.UniformLocation = function(progObj, name) { return progObj.unifomLocation[name]; } 
 
    ShaderProgram.Use = function(progObj) { gl.useProgram(progObj); } 
 
    ShaderProgram.SetUniformI1 = function(progObj, name, val) { if(progObj.unifomLocation[name]) gl.uniform1i(progObj.unifomLocation[name], val); } 
 
    ShaderProgram.SetUniformF1 = function(progObj, name, val) { if(progObj.unifomLocation[name]) gl.uniform1f(progObj.unifomLocation[name], val); } 
 
    ShaderProgram.SetUniformF2 = function(progObj, name, arr) { if(progObj.unifomLocation[name]) gl.uniform2fv(progObj.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformF3 = function(progObj, name, arr) { if(progObj.unifomLocation[name]) gl.uniform3fv(progObj.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformF4 = function(progObj, name, arr) { if(progObj.unifomLocation[name]) gl.uniform4fv(progObj.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformM33 = function(progObj, name, mat) { if(progObj.unifomLocation[name]) gl.uniformMatrix3fv(progObj.unifomLocation[name], false, mat); } 
 
    ShaderProgram.SetUniformM44 = function(progObj, name, mat) { if(progObj.unifomLocation[name]) gl.uniformMatrix4fv(progObj.unifomLocation[name], false, mat); } 
 
    ShaderProgram.CompileShader = function(source, shaderStage) { 
 
     var shaderScript = document.getElementById(source); 
 
     if (shaderScript) 
 
     source = shaderScript.text; 
 
     var shaderObj = gl.createShader(shaderStage); 
 
     gl.shaderSource(shaderObj, source); 
 
     gl.compileShader(shaderObj); 
 
     var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS); 
 
     if (!status) alert(gl.getShaderInfoLog(shaderObj)); 
 
     return status ? shaderObj : null; 
 
    } 
 
    ShaderProgram.LinkProgram = function(shaderObjs) { 
 
     var prog = gl.createProgram(); 
 
     for (var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh) 
 
      gl.attachShader(prog, shaderObjs[i_sh]); 
 
     gl.linkProgram(prog); 
 
     status = gl.getProgramParameter(prog, gl.LINK_STATUS); 
 
     if (!status) alert("Could not initialise shaders"); 
 
     gl.useProgram(null); 
 
     return status ? prog : null; 
 
    } 
 
    
 
    var VertexBuffer = {}; 
 
    VertexBuffer.Create = function(attributes, indices) { 
 
     var buffer = {}; 
 
     buffer.buf = []; 
 
     buffer.attr = [] 
 
     for (var i = 0; i < attributes.length; ++ i) { 
 
      buffer.buf.push(gl.createBuffer()); 
 
      buffer.attr.push({ size : attributes[i].attrSize, loc : attributes[i].attrLoc }); 
 
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]); 
 
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes[i].data), gl.STATIC_DRAW); 
 
     } 
 
     buffer.inx = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx); 
 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 
 
     buffer.inxLen = indices.length; 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, null); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 
 
     return buffer; 
 
    } 
 
    VertexBuffer.Draw = function(bufObj) { 
 
    for (var i = 0; i < bufObj.buf.length; ++ i) { 
 
      gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]); 
 
      gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0); 
 
      gl.enableVertexAttribArray(bufObj.attr[i].loc); 
 
     } 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx); 
 
     gl.drawElements(gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0); 
 
     for (var i = 0; i < bufObj.buf.length; ++ i) 
 
     gl.disableVertexAttribArray(bufObj.attr[i].loc); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, null); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 
 
    } 
 
    
 
    initScene(); 
 
    
 
})();
html,body { 
 
    height: 100%; 
 
    width: 100%; 
 
    margin: 0; 
 
    overflow: hidden; 
 
} 
 

 
#gui { 
 
    position : absolute; 
 
    top : 0; 
 
    left : 0; 
 
}
<script id="draw-shader-vs" type="x-shader/x-vertex"> 
 
    precision highp float; 
 
    
 
    attribute vec3 inPos; 
 
    attribute vec3 inNV; 
 
    attribute vec3 inCol; 
 
    
 
    varying vec3 vertPos; 
 
    varying vec3 vertNV; 
 
    varying vec3 vertCol; 
 
    
 
    uniform mat4 u_projectionMat44; 
 
    uniform mat4 u_viewMat44; 
 
    uniform mat4 u_modelMat44; 
 
    
 
    void main() 
 
    { 
 
     mat4 mv  = u_viewMat44 * u_modelMat44; 
 
     vertCol  = inCol; 
 
     vertNV  = normalize(mat3(mv) * inNV); 
 
     vec4 viewPos = mv * vec4(inPos, 1.0); 
 
     vertPos  = viewPos.xyz; 
 
     gl_Position = u_projectionMat44 * viewPos; 
 
    } 
 
</script> 
 
    
 
<script id="draw-shader-fs" type="x-shader/x-fragment"> 
 
    precision mediump float; 
 

 
    varying vec3 vertPos; 
 
    varying vec3 vertNV; 
 
    varying vec3 vertCol; 
 
    
 
    uniform float u_shininess; 
 
    uniform float u_glow; 
 
    
 
    void main() 
 
    { 
 
     vec3 color = vertCol; 
 
     vec3 normalV = normalize(vertNV); 
 
     vec3 eyeV  = normalize(-vertPos); 
 
     vec3 halfV = normalize(eyeV + normalV); 
 
     float NdotH = max(0.0, dot(normalV, halfV)); 
 
     float shineFac = (u_shininess + 2.0) * pow(NdotH, u_shininess)/(2.0 * 3.14159265); 
 
     gl_FragColor = vec4(color.rgb * u_glow * shineFac * 0.5, 1.0); 
 
    } 
 
</script> 
 
    
 
<script id="post-shader-vs" type="x-shader/x-vertex"> 
 
    precision mediump float; 
 
    
 
    attribute vec2 inPos; 
 
    
 
    varying vec2 pos; 
 
    
 
    void main() 
 
    { 
 
     pos = inPos; 
 
     gl_Position = vec4(inPos, 0.0, 1.0); 
 
    } 
 
</script> 
 
    
 
<script id="blurX-shader-fs" type="x-shader/x-fragment"> 
 
    precision mediump float; 
 
    
 
    varying vec2 pos; 
 
    
 
    uniform sampler2D u_texture; 
 
    uniform vec2  u_textureSize; 
 
    uniform float  u_sigma; 
 
    
 
    float CalcGauss(float x, float sigma) 
 
    { 
 
     float coeff = 1.0/(2.0 * 3.14157 * sigma); 
 
     float expon = -(x*x)/(2.0 * sigma); 
 
     return (coeff*exp(expon)); 
 
    } 
 
    
 
    void main() 
 
    { 
 
     vec2 texC = pos.st * 0.5 + 0.5; 
 
     vec4 texCol = texture2D(u_texture, texC); 
 
     vec4 gaussCol = vec4(texCol.rgb, 1.0); 
 
     float stepX = 1.0/u_textureSize.x; 
 
     for (int i = 1; i <= 20; ++ i) 
 
     { 
 
      float weight = CalcGauss(float(i)/32.0, u_sigma * 0.5); 
 
      texCol = texture2D(u_texture, texC + vec2(float(i) * stepX, 0.0)); 
 
      gaussCol += vec4(texCol.rgb * weight, weight); 
 
      texCol = texture2D(u_texture, texC - vec2(float(i) * stepX, 0.0)); 
 
      gaussCol += vec4(texCol.rgb * weight, weight); 
 
     } 
 
     gaussCol.rgb /= gaussCol.w; 
 
     gl_FragColor = vec4(gaussCol.rgb, 1.0); 
 
    } 
 
</script> 
 
    
 
<script id="blurY-shader-fs" type="x-shader/x-fragment"> 
 
    precision mediump float; 
 
    
 
    varying vec2 pos; 
 
    
 
    uniform sampler2D u_texture; 
 
    uniform vec2  u_textureSize; 
 
    uniform float  u_sigma; 
 
    
 
    float CalcGauss(float x, float sigma) 
 
    { 
 
     float coeff = 1.0/(2.0 * 3.14157 * sigma); 
 
     float expon = -(x*x)/(2.0 * sigma); 
 
     return (coeff*exp(expon)); 
 
    } 
 
    
 
    void main() 
 
    { 
 
     vec2 texC = pos.st * 0.5 + 0.5; 
 
     vec4 texCol = texture2D(u_texture, texC); 
 
     vec4 gaussCol = vec4(texCol.rgb, 1.0); 
 
     float stepY = 1.0/u_textureSize.y; 
 
     for (int i = 1; i <= 20; ++ i) 
 
     { 
 
      float weight = CalcGauss(float(i)/32.0, u_sigma * 0.5); 
 
      texCol = texture2D(u_texture, texC + vec2(0.0, float(i) * stepY)); 
 
      gaussCol += vec4(texCol.rgb * weight, weight); 
 
      texCol = texture2D(u_texture, texC - vec2(0.0, float(i) * stepY)); 
 
      gaussCol += vec4(texCol.rgb * weight, weight); 
 
     } 
 
     vec3 hdrCol = 2.0 * gaussCol.xyz/gaussCol.w; 
 
     vec3 mappedCol = vec3(1.0) - exp(-hdrCol.rgb * 3.0); 
 
     gl_FragColor = vec4(clamp(mappedCol.rgb, 0.0, 1.0), 1.0); 
 
    } 
 
</script> 
 

 
<div> 
 
    <form id="gui" name="inputs"> 
 
     <table> 
 
      <tr> <td> <font color= #CCF>shininess</font> </td> 
 
       <td> <input type="range" id="shine" min="0" max="50" value="10" onchange="changeEventHandler(event);"/></td> </tr> 
 
      <tr> <td> <font color= #CCF>glow</font> </td> 
 
       <td> <input type="range" id="glow" min="100" max="400" value="300" onchange="changeEventHandler(event);"/></td> </tr> 
 
      <tr> <td> <font color= #CCF>blur</font> </td> 
 
       <td> <input type="range" id="sigma" min="1" max="100" value="60" onchange="changeEventHandler(event);"/></td> </tr> 
 
     </table> 
 
    </form> 
 
</div> 
 

 
<canvas id="canvas" style="border: none;" width="100%" height="100%"></canvas>

+0

cảm ơn câu trả lời tuyệt vời, nhưng tại sao dòng này 'vertPos = pos.xyz/pos.w; ' trong đổ bóng đỉnh ?. là cần thiết để chia cho w ở đây. Tôi nghĩ rằng w luôn luôn là 1 ở giai đoạn này. – wdanxna

+0

@wdanxna Không có trong trường hợp này không cần thiết. – Rabbid76

Các vấn đề liên quan