<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script src="../lib/cuon-matrix.js"></script>
</head>
<body>
<canvas id="webgl" width="600" height="600">
Please use a browser that supports "canvas"
</canvas>
<script type="application/javascript">
var VSHADER_MONITOR =
'attribute vec4 a_Position;\n' +
// 'attribute vec4 a_Color;\n' + // Defined constant in main()
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_ModelMatrix;\n' +
'uniform mat4 u_ViewMatrix;\n' +
'uniform mat4 u_ProjMatrix;\n' +
'uniform mat4 u_NormalMatrix;\n' + // Transformation matrix of the normal
'varying vec3 v_Normal;\n' +
'varying vec3 v_Position;\n' +
'void main() {\n' +
' gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +
// Calculate the vertex position in the world coordinate
' v_Position = vec3(u_ModelMatrix * a_Position);\n' +
' v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
'}\n';
// Fragment shader program
var FSHADER_MONITOR =
'precision mediump float;\n' +
'uniform vec3 u_LightColor;\n' + // Light color
'uniform vec3 u_LightPosition;\n' + // Position of the light source
'uniform vec3 u_AmbientLight;\n' + // Ambient light color
'varying vec3 v_Normal;\n' +
'varying vec3 v_Position;\n' +
'void main() {\n' +
// Normalize the normal because it is interpolated and not 1.0 in length any more
' vec3 normal = normalize(v_Normal);\n' +
// Calculate the light direction and make it 1.0 in length
' vec3 lightDirection = normalize(u_LightPosition - v_Position);\n' +
// The dot product of the light direction and the normal
' float nDotL = max(dot(lightDirection, normal), 0.0);\n' +
// Calculate the final color from diffuse reflection and ambient reflection
' vec4 texColor = vec4(1,1,1,1.0);\n' +
' vec3 diffuse = u_LightColor * texColor.rgb * nDotL;\n' +
' vec3 ambient = u_AmbientLight * texColor.rgb;\n' +
' gl_FragColor = vec4(diffuse + ambient, 1);\n' +
//' gl_FragColor = vec4(visibility,0.0,0.0,1.0);\n' +
'}\n';
var VSHADER_SOURCE_DQ =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' +
'varying vec2 v_TexCoord;\n' +
// 'attribute vec4 a_Color;\n' + // Defined constant in main()
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_ModelMatrix;\n' +
'uniform mat4 u_ViewMatrix;\n' +
'uniform mat4 u_ProjMatrix;\n' +
'uniform mat4 u_NormalMatrix;\n' + // Transformation matrix of the normal
'varying vec3 v_Normal;\n' +
'varying vec3 v_Position;\n' +
'void main() {\n' +
' v_TexCoord = a_TexCoord;\n' +
' gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +
// Calculate the vertex position in the world coordinate
' v_Position = vec3(u_ModelMatrix * a_Position);\n' +
' v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE_DQ =
'precision mediump float;\n' +
'uniform vec3 u_LightColor;\n' + // Light color
'uniform vec3 u_LightPosition;\n' + // Position of the light source
'uniform vec3 u_AmbientLight;\n' + // Ambient light color
'varying vec3 v_Normal;\n' +
'varying vec3 v_Position;\n' +
'varying vec2 v_TexCoord;\n' +
'uniform sampler2D u_Sampler;\n' +
'void main() {\n' +
// Normalize the normal because it is interpolated and not 1.0 in length any more
' vec3 normal = normalize(v_Normal);\n' +
// Calculate the light direction and make it 1.0 in length
' vec3 lightDirection = normalize(u_LightPosition - v_Position);\n' +
// The dot product of the light direction and the normal
' float nDotL = max(dot(lightDirection, normal), 0.0);\n' +
// Calculate the final color from diffuse reflection and ambient reflection
' vec4 texColor = texture2D(u_Sampler, v_TexCoord);\n' +
' vec3 diffuse = u_LightColor * texColor.rgb * nDotL;\n' +
' vec3 ambient = u_AmbientLight * texColor.rgb;\n' +
' gl_FragColor = vec4(diffuse + ambient, 1);\n' +
//' gl_FragColor = vec4(visibility,0.0,0.0,1.0);\n' +
'}\n';
let movdis = 0;
let derection = 1;
var currentAngle = 0.0;
var g_last = Date.now();
var ANGLE_STEP = 45.0;
//获取webgl上下文
// Get the rendering context for WebGL
var canvas = document.getElementById('webgl');
var gl = canvas.getContext('webgl',{stencil: true});
function animate(angle) {
// Calculate the elapsed time
var now = Date.now();
var elapsed = now - g_last;
g_last = now;
// Update the current rotation angle (adjusted by the elapsed time)
var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
return newAngle %= 360;
}
window.onload = function(){
//加载地球图片
var image = new Image(); // Create the image object
// Register the event handler to be called on loading an image
image.onload = function(){
};
// Tell the browser to load an image
image.src = 'earth1.png';
setTimeout(function(){
window.renderCanvas(image)
}, 1000)
setTimeout(function(){
setInterval(function () {
window.renderCanvas(image);
currentAngle = animate(currentAngle);
}, 100);
}, 2000)
}
function drawMonitor(){
var shadowProgram_dq = createProgram(gl, VSHADER_MONITOR, FSHADER_MONITOR);
gl.useProgram(shadowProgram_dq)
gl.program = shadowProgram_dq;
// Get the storage locations of uniform variables and so on
var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
// Set the light color (white)
gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
// Set the light direction (in the world cou_MvpMatrixFromLightordinate)
gl.uniform3f(u_LightPosition, 3, 3, 8.0);
// Set the ambient light
gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);
var normalMatrix = new Matrix4(); // Transformation matrix for normals
var modelMatrix = new Matrix4(); // The model matrix
var viewMatrix = new Matrix4(); // The view matrix
var projMatrix = new Matrix4(); // The projection matrix
// Calculate the view matrix and the projection matrix
modelMatrix.setTranslate(0, 0, 0); // Translate 0.75 units along the positive x-axis
viewMatrix.setLookAt(5.0, 0.0, 28.0, 0, 0, 0, 0, 1, 0);
projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
// Pass the model, view, and projection matrix to the uniform variable respectively
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);
normalMatrix.setInverseOf(modelMatrix);
normalMatrix.transpose();
// Pass the transformation matrix for normals to u_NormalMatrix
gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
var positions = [0.0,4.0,4.0,0.0,4.0,-4.0,0.0,-4.0,-4.0,0.0,-4.0,4.0];
var indices = [0,2,1,0,3,2];
var normals = [1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0]
if (!initArrayBuffer(gl, 'a_Normal', new Float32Array(normals), gl.FLOAT, 3)) return -1;
if (!initArrayBuffer(gl, 'a_Position', new Float32Array(positions), gl.FLOAT, 3)) return -1;
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}
function renderCanvas(image){
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
//清除模板缓存
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
//开启剪裁测试
gl.enable(gl.STENCIL_TEST);
//设置模板测试参数
gl.stencilFunc(gl.ALWAYS, 1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
//画镜子
drawMonitor();
//禁用深度测试 开启剪裁测试会画出镜像
//关闭深度检测
gl.disable(gl.DEPTH_TEST);
//设置模板测试参数
gl.stencilFunc(gl.EQUAL,1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
//开启卷绕
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CW);
//开启混合
gl.enable(gl.BLEND);
//设置混合因子
gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA);
//绘制阴影贴图 用于给地球贴阴影
var shadowProgram_dq = createProgram(gl, VSHADER_SOURCE_DQ, FSHADER_SOURCE_DQ);
gl.useProgram(shadowProgram_dq)
gl.program = shadowProgram_dq;
// Set the vertex coordinates, the color and the normal
var n = initVertexBuffers2(gl,2);
// Get the storage locations of uniform variables and so on
var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
// Set the light color (white)
gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
// Set the light direction (in the world cou_MvpMatrixFromLightordinate)
gl.uniform3f(u_LightPosition, 3, 3, 8.0);
// Set the ambient light
gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);
//纹理
var texture = gl.createTexture(); // Create a texture object
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Flip the image's y axis
// Enable texture unit0
gl.activeTexture(gl.TEXTURE0);
// Bind the texture object to the target
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the texture parameters
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// Set the texture image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
// Set the texture unit 0 to the sampler
gl.uniform1i(u_Sampler, 0);
var normalMatrix = new Matrix4(); // Transformation matrix for normals
var modelMatrix = new Matrix4(); // The model matrix
var viewMatrix = new Matrix4(); // The view matrix
var projMatrix = new Matrix4(); // The projection matrix
if(movdis > 38){
if(derection == 1){
derection = 0
}
}else if (movdis < -6){
if(derection == 0){
derection = 1
}
}
if(derection == 1){
movdis +=1;
}else{
movdis +=-1;
}
// Calculate the view matrix and the projection matrix
modelMatrix.setTranslate(-3, 0, -1*movdis); // Translate 0.75 units along the positive x-axis
modelMatrix.rotate(currentAngle,0,0,1);
viewMatrix.setLookAt(5.0, 0.0, 28.0, 0, 0, 0, 0, 1, 0);
projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
// Pass the model, view, and projection matrix to the uniform variable respectively
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);
normalMatrix.setInverseOf(modelMatrix);
normalMatrix.transpose();
// Pass the transformation matrix for normals to u_NormalMatrix
gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
// Draw the cube(Note that the 3rd argument is the gl.UNSIGNED_SHORT)
//打开背景剪裁
//gl.enable(gl.CULL_FACE);
//gl.frontFace(gl.CCW);
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
//设置定点信息
var n = initVertexBuffers(gl,2);
modelMatrix.setTranslate(3, 0, -1*movdis); // Translate 0.75 units along the positive x-axis
modelMatrix.rotate(-1*currentAngle,0,0,1);
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
normalMatrix.setInverseOf(modelMatrix);
normalMatrix.transpose();
gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
//打开背景剪裁
gl.enable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);
gl.disable(gl.STENCIL_TEST);
gl.frontFace(gl.CCW);
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
}
function initVertexBuffers2(gl,size,need) {// Create a sphere
var positions = [];
var indices = [];
var SPHERE_DIV = 13;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var textures = [];
// Generate coordinates
for (j = 0; j <= SPHERE_DIV; j++) {
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++) {
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
positions.push(-1*size*si * sj); // X
positions.push(size*cj); // Y
positions.push(size*ci * sj); // Z
//设置纹理坐标
let heigh = j/SPHERE_DIV
let width = i/SPHERE_DIV
textures.push(width);
textures.push(heigh);
}
}
// Generate indices
for (j = 0; j < SPHERE_DIV; j++) {
for (i = 0; i < SPHERE_DIV; i++) {
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indices.push(p1);
indices.push(p2);
indices.push(p1 + 1);
indices.push(p1 + 1);
indices.push(p2);
indices.push(p2 + 1);
}
}
// Write the vertex property to buffers (coordinates and normals)
// Same data can be used for vertex and normal
// In order to make it intelligible, another buffer is prepared separately
if (!initArrayBuffer(gl, 'a_Position', new Float32Array(positions), gl.FLOAT, 3)) return -1;
if(!need){
if (!initArrayBuffer(gl, 'a_Normal', new Float32Array(positions), gl.FLOAT, 3)) return -1;
if (!initArrayBuffer(gl, 'a_TexCoord', new Float32Array(textures), gl.FLOAT, 2)) return -1;
}
// Unbind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// Write the indices to the buffer object
var indexBuffer = gl.createBuffer();
if (!indexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
return indices.length;
}
function initVertexBuffers(gl,size,need) {// Create a sphere
var positions = [];
var indices = [];
var SPHERE_DIV = 13;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var textures = [];
// Generate coordinates
for (j = 0; j <= SPHERE_DIV; j++) {
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++) {
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
positions.push(size*si * sj); // X
positions.push(size*cj); // Y
positions.push(size*ci * sj); // Z
//设置纹理坐标
let heigh = j/SPHERE_DIV
let width = i/SPHERE_DIV
textures.push(width);
textures.push(heigh);
}
}
// Generate indices
for (j = 0; j < SPHERE_DIV; j++) {
for (i = 0; i < SPHERE_DIV; i++) {
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indices.push(p1);
indices.push(p2);
indices.push(p1 + 1);
indices.push(p1 + 1);
indices.push(p2);
indices.push(p2 + 1);
}
}
// Write the vertex property to buffers (coordinates and normals)
// Same data can be used for vertex and normal
// In order to make it intelligible, another buffer is prepared separately
if (!initArrayBuffer(gl, 'a_Position', new Float32Array(positions), gl.FLOAT, 3)) return -1;
if(!need){
if (!initArrayBuffer(gl, 'a_Normal', new Float32Array(positions), gl.FLOAT, 3)) return -1;
if (!initArrayBuffer(gl, 'a_TexCoord', new Float32Array(textures), gl.FLOAT, 2)) return -1;
}
// Unbind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// Write the indices to the buffer object
var indexBuffer = gl.createBuffer();
if (!indexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
return indices.length;
}
function initArrayBuffer(gl, attribute, data, type, num) {
// Create a buffer object
var buffer = gl.createBuffer();
if (!buffer) {
console.log('Failed to create the buffer object');
return false;
}
// Write date into the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// Assign the buffer object to the attribute variable
var a_attribute = gl.getAttribLocation(gl.program, attribute);
if (a_attribute < 0) {
console.log('Failed to get the storage location of ' + attribute);
return false;
}
gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
// Enable the assignment of the buffer object to the attribute variable
gl.enableVertexAttribArray(a_attribute);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return true;
}
function initFramebufferObject(gl) {
var framebuffer, texture, depthBuffer;
// Define the error handling function
var error = function() {
if (framebuffer) gl.deleteFramebuffer(framebuffer);
if (texture) gl.deleteTexture(texture);
if (depthBuffer) gl.deleteRenderbuffer(depthBuffer);
return null;
}
// Create a framebuffer object (FBO)
framebuffer = gl.createFramebuffer();
if (!framebuffer) {
console.log('Failed to create frame buffer object');
return error();
}
// Create a texture object and set its size and parameters
texture = gl.createTexture(); // Create a texture object
if (!texture) {
console.log('Failed to create texture object');
return error();
}
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// Create a renderbuffer object and Set its size and parameters
depthBuffer = gl.createRenderbuffer(); // Create a renderbuffer object
if (!depthBuffer) {
console.log('Failed to create renderbuffer object');
return error();
}
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);
// Attach the texture and the renderbuffer object to the FBO
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
// Check if FBO is configured correctly
var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (gl.FRAMEBUFFER_COMPLETE !== e) {
console.log('Frame buffer object is incomplete: ' + e.toString());
return error();
}
framebuffer.texture = texture; // keep the required object
// Unbind the buffer object
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
return framebuffer;
}
</script>
</body>
</html>
地球纹理图片