Webgl中的阴影

如何解决Webgl中的阴影

我一直在尝试在webgl中创建阴影,如下图所示:在这里我们可以看到一个圆锥体,一个球体和一个灯光(我们可以使用滑块更改其位置)。

enter image description here

我试图通过从一些webgl辅导网站上看到多个阴影示例来在html文件中编写一些代码,但是现在,我什至看不到形状。可以肯定我做错了什么,但我只是不知道在哪里。这是我的代码,我还包含一个链接,因为它包含多个文件。预先感谢。

链接:https://wetransfer.com/downloads/cd0f66f2e2866c0d118e95b02e01cb0520200923203442/274553

<html>

<head>
<title>Light and Shading</title>
<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>

<!-- CSS Styles //-->
<link href='css/style.css'   type='text/css' rel='stylesheet'>
<link href='css/desert.css'  type='text/css' rel='stylesheet'/>
<link href='css/colorpicker.css'  type='text/css' rel='stylesheet'/>
<link href='css/smoothness/jquery-ui-1.8.13.custom.css' type='text/css' rel='stylesheet' />

<!-- JavaScript Libraries //-->
<script type='text/javascript' src='js/gl-matrix-min.js'></script>
<script type='text/javascript' src='js/jquery-1.5.1.min.js'></script>
<script type='text/javascript' src='js/jquery-ui-1.8.13.custom.min.js'></script> 
<script type='text/javascript' src='js/prettify.js'></script>
<script type='text/javascript' src='js/utils.js'></script>
<script type='text/javascript' src='js/colorpicker.js'></script>
<script type='text/javascript' src='js/codeview.js'></script>

<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec3 aVertexNormal;

    // matrice model-view combinee.
    uniform mat4 uMVMatrix;

    // matrice de projection
    uniform mat4 uPMatrix;

    // matrice des normales.
    uniform mat3 uNMatrix;

    // position de la lumiere.
    uniform vec3 uLightPosition;

    // La normale transformee
    varying vec3 vNormal;

    // la direction vertex-lumiere
    varying vec3 vLightRay;

    // la direction camera-vertex
    varying vec3 vEyeVec;

    uniform vec4 uLightAmbient;
    uniform vec4 uLightDiffuse;
    uniform vec4 uLightSpecular;

    uniform vec4 uMaterialAmbient;
    uniform vec4 uMaterialDiffuse;
    uniform vec4 uMaterialSpecular;


    void main(void) {


    vec4 ambientProduct= uLightAmbient* uMaterialAmbient;
    vec4 diffuseProduct= uLightDiffuse*uMaterialDiffuse;
    vec4 specularProduct= uLightSpecular*uMaterialSpecular;

    vec3 pos = (uMVMatrix*vec4(aVertexPosition,1.0)).xyz;


    // position de l'oeil/camera.
    const vec3 eyePosition = vec3(0,-40);

    //Transformed normal position
    vNormal = normalize((uNMatrix* aVertexNormal).xyz) ;

    //Transformed light position
    vec4 light = uMVMatrix * vec4(uLightPosition,1.0);

    vec3 lightPos = (uMVMatrix * light).xyz;

    //Light position
    vLightRay = normalize(pos - lightPos);

    //Vector Eye
    vEyeVec = -normalize(pos);


    //Final vertex position
    gl_Position = uMVMatrix*uPMatrix* vec4(aVertexPosition,1.0);

    }
</script>

<script id="shader-fs" type="x-shader/x-fragment">
    #ifdef GL_ES
    precision highp float;
    #endif

    varying vec3 vNormal;
    varying vec3 vLightRay;
    varying vec3 vEyeVec;

    uniform vec4 ambientProduct;
    uniform vec4 diffuseProduct;
    uniform vec4 specularProduct;
    uniform float uShininess;

    void main(void)
    {

    vec4 diffuse = max(dot( vNormal,vLightRay),0.0) * diffuseProduct;
    vec3 H = normalize(vLightRay+vEyeVec);
    vec4 specular =
    pow(max(dot(vNormal,H),0.0),uShininess) * specularProduct;
    if (dot(vLightRay,vNormal) < 0.0)
    specular = vec4(0.0,0.0,1.0);

    vec4 fColor = ambientProduct + diffuse + specular;
    fColor.a = 1.0;
    gl_FragColor =fColor;

    }
</script>



<script id='code-js' type="text/javascript">

var gl = null; // WebGL context
var prg = null; // The program (shaders)
var c_width = 0; // Variable to store the width of the canvas
var c_height = 0; // Variable to store the height of the canvas

var mvMatrix = mat4.create(); // The Model-View matrix
var pMatrix = mat4.create(); // The projection matrix
var nMatrix =  mat4.create();      // The normal matrix

var distance = -40;
var animateFlag = false;

var objects = [];   

/**
* The program contains a series of instructions that tell the Graphic Processing Unit (GPU)
* what to do with every vertex and fragment that we pass it. 
* The vertex shader and the fragment shader together are called the program.
*/
function initProgram() {
var fragmentShader      = utils.getShader(gl,"shader-fs");
var vertexShader        = utils.getShader(gl,"shader-vs");

prg = gl.createProgram();
gl.attachShader(prg,vertexShader);
gl.attachShader(prg,fragmentShader);
gl.linkProgram(prg);

if (!gl.getProgramParameter(prg,gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}

gl.useProgram(prg);

prg.aVertexPosition     = gl.getAttribLocation(prg,"aVertexPosition");
prg.aVertexNormal       = gl.getAttribLocation(prg,"aVertexNormal");

prg.uPMatrix            = gl.getUniformLocation(prg,"uPMatrix");
prg.uMVMatrix           = gl.getUniformLocation(prg,"uMVMatrix");
prg.uNMatrix            = gl.getUniformLocation(prg,"uNMatrix");


prg.uMaterialAmbient    = gl.getUniformLocation(prg,"uMaterialAmbient");
prg.uMaterialDiffuse    = gl.getUniformLocation(prg,"uMaterialDiffuse");
prg.uMaterialSpecular   = gl.getUniformLocation(prg,"uMaterialSpecular");
prg.uShininess          = gl.getUniformLocation(prg,"uShininess");


prg.uLightPosition      = gl.getUniformLocation(prg,"uLightPosition");
prg.uLightAmbient       = gl.getUniformLocation(prg,"uLightAmbient");
prg.uLightDiffuse       = gl.getUniformLocation(prg,"uLightDiffuse");
prg.uLightSpecular      = gl.getUniformLocation(prg,"uLightSpecular");
}


function initLights(){
//Light uniforms
gl.uniform3fv(prg.uLightPosition,[4.5,3.0,15.0]);        
gl.uniform4f(prg.uLightAmbient,1.0,1.0);
gl.uniform4f(prg.uLightDiffuse,1.0);
gl.uniform4f(prg.uLightSpecular,1.0);

//Object Uniforms
gl.uniform4f(prg.uMaterialAmbient,0.1,1.0);
gl.uniform4f(prg.uMaterialDiffuse,0.5,0.8,1.0);
gl.uniform4f(prg.uMaterialSpecular,0.6,1.0);
gl.uniform1f(prg.uShininess,200.0);

}


/**
* Creates an AJAX request to load the scene asynchronously
*/
function loadScene(){
loadObject('models/plane.json');
loadObject('models/cone.json','cone');
loadObject('models/sphere.json','sphere');
loadObject('models/smallsph.json','lightsource');
}

function getObject(alias){
for(var i=0; i<objects.length; i++){
if (alias == objects[i].alias) return objects[i];
}
return null;
}

/**
* Ajax and JSON in action
*/ 

function loadObject(filename,alias){
    var request = new XMLHttpRequest();
    console.info('Requesting ' + filename);
    request.open("GET",filename);
    
    request.onreadystatechange = function() {
    if (request.readyState == 4) {
        if(request.status == 404) {
            console.info(filename + ' does not exist');
        }
        else {
var o = JSON.parse(request.responseText);
o.alias = (alias==null)?'none':alias;
            handleLoadedObject(filename,o);
        }
    }
    }
    request.send();
}

/**
* Creates the buffers that contain the geometry of the object
*/
function handleLoadedObject(filename,object) {
    
    console.info(filename + ' has been retrieved from the server');
    
    var vertexBufferObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,vertexBufferObject);
    gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(object.vertices),gl.STATIC_DRAW);
    
        
    var normalBufferObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,normalBufferObject);
    gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(calcNormals(object.vertices,object.indices)),gl.STATIC_DRAW);
    
    var indexBufferObject = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBufferObject);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(object.indices),gl.STATIC_DRAW);
        
    
    object.vbo = vertexBufferObject;
    object.ibo = indexBufferObject;
    object.nbo = normalBufferObject;

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
    gl.bindBuffer(gl.ARRAY_BUFFER,null);
    
    objects.push(object);
} 

/**
* Main rendering function. Called every 500ms according to WebGLStart function (see below)
*/
function drawScene() {
    gl.clearColor(0.3,0.3,1.0);
    gl.clearDepth(100.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.viewport(0,c_width,c_height);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    mat4.perspective(60,c_width / c_height,1000.0,pMatrix);

    try{
        gl.enableVertexAttribArray(prg.aVertexPosition);
        gl.enableVertexAttribArray(prg.aVertexNormal);
        for (var i = 0; i < objects.length; i++){
            var object = objects[i];
            mat4.identity(mvMatrix);
            mat4.translate(mvMatrix,[0.0,distance]); //Sets the camera to a reasonable distance to view the part
            mat4.rotate(mvMatrix,30*Math.PI/180,[1,0]);
            mat4.rotate(mvMatrix,angle*Math.PI/180,[0,1,0]);
            if (object.alias == 'lightsource'){
                var lightPos = gl.getUniform(prg,prg.uLightPosition);
                mat4.translate(mvMatrix,lightPos);
                
            }
            
            gl.uniformMatrix4fv(prg.uMVMatrix,false,mvMatrix);
            gl.uniformMatrix4fv(prg.uPMatrix,pMatrix);
            mat4.set(mvMatrix,nMatrix);
            mat4.inverse(nMatrix);
            mat4.transpose(nMatrix);
            
            gl.uniformMatrix4fv(prg.uNMatrix,nMatrix);
            gl.uniform4fv(prg.uMaterialAmbient,object.ambient);
            gl.uniform4fv(prg.uMaterialDiffuse,object.diffuse);
            gl.uniform4fv(prg.uMaterialSpecular,object.specular);
            gl.bindBuffer(gl.ARRAY_BUFFER,object.vbo);
            gl.vertexAttribPointer(prg.aVertexPosition,3,gl.FLOAT,0);
            gl.enableVertexAttribArray(prg.aVertexPosition);
            
            gl.bindBuffer(gl.ARRAY_BUFFER,object.nbo);
            gl.vertexAttribPointer(prg.aVertexNormal,0);
            gl.enableVertexAttribArray(prg.aVertexNormal);
            
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,object.ibo);
            gl.drawElements(gl.TRIANGLES,object.indices.length,gl.UNSIGNED_SHORT,0);
            gl.bindBuffer(gl.ARRAY_BUFFER,null);
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
        }
    }
    catch(err){
        alert(err);
        message(err.description);
    }
}






var lastTime = 0;
var angle = 0;
/**
* Updates the angle of rotation by a little bit each time
*/
function animate() {
    var timeNow = new Date().getTime();
    if (lastTime != 0) {
        var elapsed = timeNow - lastTime;
        if (animateFlag) angle += (90 * elapsed) / 10000.0;
    }
    lastTime = timeNow;
}

/**
* Render Loop
*/
function renderLoop() {
    requestAnimFrame(renderLoop);
    drawScene();
animate();
}

/**
* Entry point. This function is invoked when the page is loaded
*/
function runWebGLApp() {
//Obtains a WebGL context
gl = utils.getGLContext("canvas-element-id");
//Initializes the program (shaders) 
    initProgram();
    //Initializes lights
    initLights();
    //Load Scene
loadScene();
    //Renders the scene!
    renderLoop();
}
</script>
</head>

<body onLoad='runWebGLApp()'>
<div id='top'>

<div id='contents'>
<div id='canvasContainer'>
<canvas id='canvas-element-id' width='480' height='400'>
Your browser does not support the HTML5 canvas element.
</canvas>
</div>
</div>

<div id='bottom'>
<table style='padding=0px'>
<tr>
<td>X:</td><td id='slider-x-value' width='30px'>4.5</td><td width='150px'><div id='slider-x'/></td>
</tr>
<tr>
<td>Y:</td><td id='slider-y-value'  width='30px'>3.0</td><td width='150px'><div id='slider-y'/></td>
</tr>
<tr>
<td>Z:</td> <td id='slider-z-value'  width='30px'>15.0</td><td width='150px'><div id='slider-z'/></td>
</tr>
</table>
</div>
<script>cview.run(cview.MODE_VIEW);</script>
<script> 
$('#slider-shininess').slider({value:200,min:1,max:300,step:1,slide:updateShininess});
$('#slider-x').slider({value:4.5,min:-50,max:50,step:0.1,slide:updateLightPosition,change:updateLightPosition});
$('#slider-y').slider({value:3.0,min:0,change:updateLightPosition});
$('#slider-z').slider({value:15.0,change:updateLightPosition});


$('#animate-btn').button();
$('#animate-btn').click(
function(){
    if ($('#animate-btn:checked').val()==null){
        animateFlag = false;
    }
    else{
        animateFlag = true;
    }
});
function updateShininess(){
    var v = $('#slider-shininess').slider("value");
    gl.uniform1f(prg.uShininess,v);
    $('#slider-shininess-value').html(v);
}



function updateLightPosition(){
    var x = $('#slider-x').slider("value");
    var y = $('#slider-y').slider("value");
    var z = $('#slider-z').slider("value");
    gl.uniform3fv(prg.uLightPosition,[x,y,z]);
    $('#slider-x-value').html(x);
    $('#slider-y-value').html(y);
    $('#slider-z-value').html(z);
}


function updateDistance(){
    var d = $('#slider-distance').slider("value");
    $('#slider-distance-value').html(distance);
    distance = -d;
}



function updateObjectColor(alias,r,g,b){
    var object = getObject(alias);
    if (object != null){
        object.diffuse = [r,b,1.0];
    }

}

$('#colorSelectorSphere').ColorPicker({
onSubmit: function(hsb,hex,rgb,el) {
        $(el).val(hex);
        $(el).ColorPickerHide();

    },color: '#00ff00',onShow: function (colpkr) {
        $(colpkr).fadeIn(500);
        return false;
    },onHide: function (colpkr) {
        $(colpkr).fadeOut(500);
        return false;
    },onChange: function (hsb,rgb) {
        $('#colorSelectorSphere div').css('backgroundColor','#' + hex);
        updateObjectColor('sphere',rgb.r/256,rgb.g/256,rgb.b/256);
    },onBeforeShow: function (colpkr) {
        $(this).ColorPickerSetColor('rgb(0.5,0.1)');
    }
})

$('#colorSelectorCone').ColorPicker({
onSubmit: function(hsb,rgb) {
        $('#colorSelectorCone div').css('backgroundColor','#' + hex);
        updateObjectColor('cone',onBeforeShow: function (colpkr) {
        $(this).ColorPickerSetColor('rgb(0.8,0.5)');
    }
}) 


// Calcule les normales des vertex. La normale de chaque vertex est
// la moyenne des triangles voisins.
//
// vertices: la liste des vertex.
// ind: la liste des indices.
// retour: la liste des normales par vertex.
function calcNormals(vertices,ind){
  var x=0; 
  var y=1;
  var z=2;
    var v1 = [],v2 = [],thisNormal = [];

    // initialiser la liste des normales.
  var ns = [];
  for(var i=0;i<vertices.length;i++)
    {
    ns[i]=0.0;
  }

  for(var i=0;i<ind.length;i=i+3){
    //v1 = p1 - p0
    v1[x] = vertices[3*ind[i+1]+x] - vertices[3*ind[i]+x];
    v1[y] = vertices[3*ind[i+1]+y] - vertices[3*ind[i]+y];
    v1[z] = vertices[3*ind[i+1]+z] - vertices[3*ind[i]+z];

    // v2 = p2 - p1
    v2[x] = vertices[3*ind[i+2]+x] - vertices[3*ind[i]+x];
    v2[y] = vertices[3*ind[i+2]+y] - vertices[3*ind[i]+y];
    v2[z] = vertices[3*ind[i+2]+z] - vertices[3*ind[i]+z];            

    // N = v2 x v1 (cross product).
    thisNormal[x] = v1[y]*v2[z] - v1[z]*v2[y];
    thisNormal[y] = v1[z]*v2[x] - v1[x]*v2[z];
    thisNormal[z] = v1[x]*v2[y] - v1[y]*v2[x];

    for(j=0;j<3;j++)
        {
            // N += thisNormal. on additionne les normales. 
      ns[3*ind[i+j]+x] =  ns[3*ind[i+j]+x] + thisNormal[x];
      ns[3*ind[i+j]+y] =  ns[3*ind[i+j]+y] + thisNormal[y];
      ns[3*ind[i+j]+z] =  ns[3*ind[i+j]+z] + thisNormal[z];
    }
  }

  // Normalisation.
  for(var i=0;i<vertices.length;i=i+3){ 

    var nn=[];
        var len = 0;
        for(var j = 0; j < 3; j++)
        {
            nn[j] = ns[i+j];
            len += nn[j] * nn[j];
        }

        // La norme de la normale.
        len = Math.sqrt(len);
    if (len == 0) 
            len = 0.00001;

        for(var j = 0; j < 3; j++)
        ns[i+j] = nn[j] / len;

        console.log(len);
  }

  return ns;
}

</script>
</body>
</html>

解决方法

老实说,有太多问题需要解决。试图使您的代码工作。首先,您真的需要学习如何进行最小的回购。您发布的代码无法运行,引用了几个不存在的脚本以及不存在的数据。

该代码所基于的教程似乎过时了。在2020年,没有人使用XMLHttpRequest。没有requestAnimFrame这样的功能是requestAnimationFrame。我认为这是从2011年以来的polyfill遗留下来的。它仍在使用<body onload="">,现在已经很少使用了。它还使用new Date().getTime(),由于时间已传递到requestAnimationFrame中,因此没有理由使用。它正在调用某些函数来获取webgl上下文,但在2020年也没有理由。它显然也使用了旧版本的glMatrix,因为the current version使用了不同的API。在当前版本中,每个函数都采用一个矩阵来存储结果作为第一个参数。同样在当前版本中,perspective的视场以弧度为单位。我不知道它是否曾经用度来表示,但是代码通过了度。

我将XHR代码更改为仅返回一个多维数据集。 (“最小可验证示例”(mcve)的最小和完整部分的示例-我认为现在SO称它们为“最小可复制示例”。我还删除了对ColorPicker的所有引用(另一个示例进行最小的回购)

该代码在the JavaScript console中应该出现错误。您是否检查过JavaScript控制台?特别是uNMatrix是mat3,但是代码正在调用gl.uniformMatrix4fv来设置它,这是一个错误。

使用webgl-lint指出没有设置几套制服,包括“ ambientProduct”,“ diffuseProduct”,“ specularProduct”,还有几套不存在的制服(那部分不一定是bug),但是有顶点着色器中有几套实际不使用的制服,例如颜色似乎设置为

gl.uniform4fv(prg.uMaterialAmbient,object.ambient);
gl.uniform4fv(prg.uMaterialDiffuse,object.diffuse);
gl.uniform4fv(prg.uMaterialSpecular,object.specular);

但是着色器中没有使用这些制服(它们出现在着色器中,但是如果您查看代码,将看不到任何效果)

然后,当我终于摆脱了所有错误之后,剩下的要在屏幕上显示内容的问题是gl_Position的数学运算使2个矩阵向后移动。应该是projection * modelView * position,但是它有modelView * projection * position

但是,此外,所有3个模型都绘制在同一位置。那些模型中的几何可能位于不同的位置。我不知道,但通常您希望根据循环索引或某些位置数组或每个对象的数据,将所绘制的每件事以某种形式赋予其自己的位置。

无论如何,这会在屏幕上显示一些东西,但是已经花费了45分钟,我不想尝试修复照明。相反,我建议您阅读一些最新的教程,例如this one及其链接的教程。

var mat4 = glMatrix.mat4;
var gl = null; // WebGL context
var prg = null; // The program (shaders)
var c_width = 480; // Variable to store the width of the canvas
var c_height = 400; // Variable to store the height of the canvas

var mvMatrix = mat4.create(); // The Model-View matrix
var pMatrix = mat4.create(); // The projection matrix
var nMatrix = mat4.create(); // The normal matrix

var distance = -40;
var animateFlag = false;

var objects = [];

const utils = {
  getShader(gl,id) {
    const elem = document.getElementById(id);
    const type = /vertex/.test(elem.type) ?
      gl.VERTEX_SHADER :
      gl.FRAGMENT_SHADER;
    const sh = gl.createShader(type);
    gl.shaderSource(sh,elem.text);
    gl.compileShader(sh);
    if (!gl.getShaderParameter(sh,gl.COMPILE_STATUS)) {
      throw new Error(gl.getShaderInfoLog(sh));
    }
    return sh;
  },};

/**
 * The program contains a series of instructions that tell the Graphic Processing Unit (GPU)
 * what to do with every vertex and fragment that we pass it. 
 * The vertex shader and the fragment shader together are called the program.
 */
function initProgram() {
  var fragmentShader = utils.getShader(gl,"shader-fs");
  var vertexShader = utils.getShader(gl,"shader-vs");

  prg = gl.createProgram();
  gl.attachShader(prg,vertexShader);
  gl.attachShader(prg,fragmentShader);
  gl.linkProgram(prg);

  if (!gl.getProgramParameter(prg,gl.LINK_STATUS)) {
    alert("Could not initialise shaders");
  }

  gl.useProgram(prg);

  prg.aVertexPosition = gl.getAttribLocation(prg,"aVertexPosition");
  prg.aVertexNormal = gl.getAttribLocation(prg,"aVertexNormal");

  prg.uPMatrix = gl.getUniformLocation(prg,"uPMatrix");
  prg.uMVMatrix = gl.getUniformLocation(prg,"uMVMatrix");
  prg.uNMatrix = gl.getUniformLocation(prg,"uNMatrix");


  prg.uMaterialAmbient = gl.getUniformLocation(prg,"uMaterialAmbient");
  prg.uMaterialDiffuse = gl.getUniformLocation(prg,"uMaterialDiffuse");
  prg.uMaterialSpecular = gl.getUniformLocation(prg,"uMaterialSpecular");
  prg.uShininess = gl.getUniformLocation(prg,"uShininess");


  prg.uLightPosition = gl.getUniformLocation(prg,"uLightPosition");
  prg.uLightAmbient = gl.getUniformLocation(prg,"uLightAmbient");
  prg.uLightDiffuse = gl.getUniformLocation(prg,"uLightDiffuse");
  prg.uLightSpecular = gl.getUniformLocation(prg,"uLightSpecular");
  
  prg.ambientProduct = gl.getUniformLocation(prg,"ambientProduct");
  prg.diffuseProduct = gl.getUniformLocation(prg,"diffuseProduct");
  prg.specularProduct = gl.getUniformLocation(prg,"specularProduct");
}


function initLights() {
  //Light uniforms
  gl.uniform3fv(prg.uLightPosition,[4.5,3.0,15.0]);
  gl.uniform4f(prg.uLightAmbient,1.0,1.0);
  gl.uniform4f(prg.uLightDiffuse,1.0);
  gl.uniform4f(prg.uLightSpecular,1.0);

  //Object Uniforms
  gl.uniform4f(prg.uMaterialAmbient,0.1,1.0);
  gl.uniform4f(prg.uMaterialDiffuse,0.5,0.8,1.0);
  gl.uniform4f(prg.uMaterialSpecular,0.6,1.0);
  gl.uniform1f(prg.uShininess,200.0);
}


/**
 * Creates an AJAX request to load the scene asynchronously
 */
function loadScene() {
  loadObject('models/plane.json');
  loadObject('models/cone.json','cone');
  loadObject('models/sphere.json','sphere');
  loadObject('models/smallsph.json','lightsource');
}

function getObject(alias) {
  for (var i = 0; i < objects.length; i++) {
    if (alias == objects[i].alias) return objects[i];
  }
  return null;
}

/**
 * Ajax and JSON in action
 */

const vertices = [
  -1,-1,1,];
let modelNum = 0
function loadObject(filename,alias) {
  setTimeout(() => {
    const o = {
      alias: (alias == null) ? 'none' : alias,ambient: [0.1,1],diffuse: [Math.random(),Math.random(),specular: [1,// to make up for the fact the code does not have different positions
      // for each model we'll move the vertices (bad)
      vertices: vertices.map((v,i) => i % 3 === 0 ? v + modelNum * 3 : v),indices: [
        0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,],};
    handleLoadedObject(filename,o);
    ++modelNum;
  });
}

/**
 * Creates the buffers that contain the geometry of the object
 */
function handleLoadedObject(filename,object) {

  //console.info(filename + ' has been retrieved from the server');

  var vertexBufferObject = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER,vertexBufferObject);
  gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(object.vertices),gl.STATIC_DRAW);


  var normalBufferObject = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER,normalBufferObject);
  gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(calcNormals(object.vertices,object.indices)),gl.STATIC_DRAW);

  var indexBufferObject = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBufferObject);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(object.indices),gl.STATIC_DRAW);


  object.vbo = vertexBufferObject;
  object.ibo = indexBufferObject;
  object.nbo = normalBufferObject;

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
  gl.bindBuffer(gl.ARRAY_BUFFER,null);

  objects.push(object);
}

/**
 * Main rendering function. Called every 500ms according to WebGLStart function (see below)
 */
function drawScene() {
  gl.clearColor(0.3,0.3,1.0);
  //gl.clearDepth(100.0);
  gl.enable(gl.DEPTH_TEST);
  gl.depthFunc(gl.LEQUAL);
  gl.viewport(0,c_width,c_height);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  mat4.perspective(pMatrix,60 * Math.PI / 180,c_width / c_height,1000.0);

  gl.enableVertexAttribArray(prg.aVertexPosition);
  gl.enableVertexAttribArray(prg.aVertexNormal);
  for (var i = 0; i < objects.length; i++) {
    var object = objects[i];
    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix,mvMatrix,[0.0,0.0,distance]); //Sets the camera to a reasonable distance to view the part
    mat4.rotate(mvMatrix,30 * Math.PI / 180,[1,0]);
    mat4.rotate(mvMatrix,angle * Math.PI / 180,[0,0]);
    if (object.alias == 'lightsource') {
      var lightPos = gl.getUniform(prg,prg.uLightPosition);
      mat4.translate(mvMatrix,lightPos);

    }

    gl.uniformMatrix4fv(prg.uMVMatrix,false,mvMatrix);
    gl.uniformMatrix4fv(prg.uPMatrix,pMatrix);
    mat4.set(mvMatrix,nMatrix);
    mat4.invert(nMatrix,nMatrix);
    mat4.transpose(nMatrix,nMatrix);

    const t3 = glMatrix.mat3.create();
    glMatrix.mat3.fromMat4(t3,nMatrix);
    gl.uniformMatrix3fv(prg.uNMatrix,t3);
    gl.uniform4fv(prg.ambientProduct,object.ambient);
    gl.uniform4fv(prg.diffuseProduct,object.diffuse);
    gl.uniform4fv(prg.specularProduct,object.specular);
    gl.bindBuffer(gl.ARRAY_BUFFER,object.vbo);
    gl.vertexAttribPointer(prg.aVertexPosition,gl.FLOAT,0);
    gl.enableVertexAttribArray(prg.aVertexPosition);

    gl.bindBuffer(gl.ARRAY_BUFFER,object.nbo);
    gl.vertexAttribPointer(prg.aVertexNormal,0);
    gl.enableVertexAttribArray(prg.aVertexNormal);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,object.ibo);
    gl.drawElements(gl.TRIANGLES,object.indices.length,gl.UNSIGNED_SHORT,0);
    gl.bindBuffer(gl.ARRAY_BUFFER,null);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
  }
}

var lastTime = 0;
var angle = 0;
/**
 * Updates the angle of rotation by a little bit each time
 */
function animate() {
  var timeNow = new Date().getTime();
  if (lastTime != 0) {
    var elapsed = timeNow - lastTime;
    if (animateFlag) angle += (90 * elapsed) / 10000.0;
  }
  lastTime = timeNow;
}

/**
 * Render Loop
 */
function renderLoop() {
  drawScene();
  animate();
  requestAnimationFrame(renderLoop);
}

/**
 * Entry point. This function is invoked when the page is loaded
 */
function runWebGLApp() {
  //Obtains a WebGL context
  gl = document.getElementById("canvas-element-id").getContext('webgl');
  //Initializes the program (shaders) 
  initProgram();
  //Initializes lights
  initLights();
  //Load Scene
  loadScene();
  //Renders the scene!
  renderLoop();
}

$('#slider-shininess').slider({
  value: 200,min: 1,max: 300,step: 1,slide: updateShininess
});
$('#slider-x').slider({
  value: 4.5,min: -50,max: 50,step: 0.1,slide: updateLightPosition,change: updateLightPosition
});
$('#slider-y').slider({
  value: 3.0,min: 0,change: updateLightPosition
});
$('#slider-z').slider({
  value: 15.0,change: updateLightPosition
});


$('#animate-btn').button();
$('#animate-btn').click(
  function() {
    if ($('#animate-btn:checked').val() == null) {
      animateFlag = false;
    } else {
      animateFlag = true;
    }
  });

function updateShininess() {
  var v = $('#slider-shininess').slider("value");
  gl.uniform1f(prg.uShininess,v);
  $('#slider-shininess-value').html(v);
}



function updateLightPosition() {
  var x = $('#slider-x').slider("value");
  var y = $('#slider-y').slider("value");
  var z = $('#slider-z').slider("value");
  gl.uniform3fv(prg.uLightPosition,[x,y,z]);
  $('#slider-x-value').html(x);
  $('#slider-y-value').html(y);
  $('#slider-z-value').html(z);
}


function updateDistance() {
  var d = $('#slider-distance').slider("value");
  $('#slider-distance-value').html(distance);
  distance = -d;
}



function updateObjectColor(alias,r,g,b) {
  var object = getObject(alias);
  if (object != null) {
    object.diffuse = [r,b,1.0];
  }

}

// Calcule les normales des vertex. La normale de chaque vertex est
// la moyenne des triangles voisins.
//
// vertices: la liste des vertex.
// ind: la liste des indices.
// retour: la liste des normales par vertex.
function calcNormals(vertices,ind) {
  var x = 0;
  var y = 1;
  var z = 2;
  var v1 = [],v2 = [],thisNormal = [];

  // initialiser la liste des normales.
  var ns = [];
  for (var i = 0; i < vertices.length; i++) {
    ns[i] = 0.0;
  }

  for (var i = 0; i < ind.length; i = i + 3) {
    //v1 = p1 - p0
    v1[x] = vertices[3 * ind[i + 1] + x] - vertices[3 * ind[i] + x];
    v1[y] = vertices[3 * ind[i + 1] + y] - vertices[3 * ind[i] + y];
    v1[z] = vertices[3 * ind[i + 1] + z] - vertices[3 * ind[i] + z];

    // v2 = p2 - p1
    v2[x] = vertices[3 * ind[i + 2] + x] - vertices[3 * ind[i] + x];
    v2[y] = vertices[3 * ind[i + 2] + y] - vertices[3 * ind[i] + y];
    v2[z] = vertices[3 * ind[i + 2] + z] - vertices[3 * ind[i] + z];

    // N = v2 x v1 (cross product).
    thisNormal[x] = v1[y] * v2[z] - v1[z] * v2[y];
    thisNormal[y] = v1[z] * v2[x] - v1[x] * v2[z];
    thisNormal[z] = v1[x] * v2[y] - v1[y] * v2[x];

    for (j = 0; j < 3; j++) {
      // N += thisNormal. on additionne les normales. 
      ns[3 * ind[i + j] + x] = ns[3 * ind[i + j] + x] + thisNormal[x];
      ns[3 * ind[i + j] + y] = ns[3 * ind[i + j] + y] + thisNormal[y];
      ns[3 * ind[i + j] + z] = ns[3 * ind[i + j] + z] + thisNormal[z];
    }
  }

  // Normalisation.
  for (var i = 0; i < vertices.length; i = i + 3) {

    var nn = [];
    var len = 0;
    for (var j = 0; j < 3; j++) {
      nn[j] = ns[i + j];
      len += nn[j] * nn[j];
    }

    // La norme de la normale.
    len = Math.sqrt(len);
    if (len == 0)
      len = 0.00001;

    for (var j = 0; j < 3; j++)
      ns[i + j] = nn[j] / len;
  }

  return ns;
}

runWebGLApp();
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet">
<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec3 aVertexNormal;

    // matrice model-view combinee.
    uniform mat4 uMVMatrix;

    // matrice de projection
    uniform mat4 uPMatrix;

    // matrice des normales.
    uniform mat3 uNMatrix;

    // position de la lumiere.
    uniform vec3 uLightPosition;

    // La normale transformee
    varying vec3 vNormal;

    // la direction vertex-lumiere
    varying vec3 vLightRay;

    // la direction camera-vertex
    varying vec3 vEyeVec;

    uniform vec4 uLightAmbient;
    uniform vec4 uLightDiffuse;
    uniform vec4 uLightSpecular;

    uniform vec4 uMaterialAmbient;
    uniform vec4 uMaterialDiffuse;
    uniform vec4 uMaterialSpecular;


    void main(void) {


    vec4 ambientProduct= uLightAmbient* uMaterialAmbient;
    vec4 diffuseProduct= uLightDiffuse*uMaterialDiffuse;
    vec4 specularProduct= uLightSpecular*uMaterialSpecular;

    vec3 pos = (uMVMatrix*vec4(aVertexPosition,1.0)).xyz;


    // position de l'oeil/camera.
    const vec3 eyePosition = vec3(0,-40);

    //Transformed normal position
    vNormal = normalize((uNMatrix* aVertexNormal).xyz) ;

    //Transformed light position
    vec4 light = uMVMatrix * vec4(uLightPosition,1.0);

    vec3 lightPos = (uMVMatrix * light).xyz;

    //Light position
    vLightRay = normalize(pos - lightPos);

    //Vector Eye
    vEyeVec = -normalize(pos);


    //Final vertex position
    gl_Position = uPMatrix*uMVMatrix* vec4(aVertexPosition,1.0);

    }
</script>

<script id="shader-fs" type="x-shader/x-fragment">
    #ifdef GL_ES
    precision highp float;
    #endif

    varying vec3 vNormal;
    varying vec3 vLightRay;
    varying vec3 vEyeVec;

    uniform vec4 ambientProduct;
    uniform vec4 diffuseProduct;
    uniform vec4 specularProduct;
    uniform float uShininess;

    void main(void)
    {

    vec4 diffuse = max(dot( vNormal,vLightRay),0.0) * diffuseProduct;
    vec3 H = normalize(vLightRay+vEyeVec);
    vec4 specular =
    pow(max(dot(vNormal,H),0.0),uShininess) * specularProduct;
    if (dot(vLightRay,vNormal) < 0.0)
    specular = vec4(0.0,1.0);

    vec4 fColor = ambientProduct + diffuse + specular;
    fColor.a = 1.0;
    gl_FragColor =fColor;

    }
</script>



<div id='top'>

<div id='contents'>
<div id='canvasContainer'>
<canvas id='canvas-element-id' width='480' height='400'>
Your browser does not support the HTML5 canvas element.
</canvas>
</div>
</div>

<div id='bottom'>
<table style='padding=0px'>
<tr>
<td>X:</td><td id='slider-x-value' width='30px'>4.5</td><td width='150px'><div id='slider-x'/></td>
</tr>
<tr>
<td>Y:</td><td id='slider-y-value'  width='30px'>3.0</td><td width='150px'><div id='slider-y'/></td>
</tr>
<tr>
<td>Z:</td> <td id='slider-z-value'  width='30px'>15.0</td><td width='150px'><div id='slider-z'/></td>
</tr>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix-min.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://greggman.github.io/webgl-lint/webgl-lint.js"
  data-gman-debug-helper='
    {
      "warnUndefinedUniforms": false
    }
  '
></script>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-