如何解决WebGL中相机的范围滑块
我正在尝试使用范围滑块来更改Webgl中的远平面和相机的角度,但是我不能。为了使我的代码能够从滑块读取值,然后从相机的角度更改值,该怎么做?
// Application info.
var app = app || {};
function initGL() {
var gl = app.gl;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.viewport(0,app.can.width,app.can.height);
gl.clearColor(0.,0.,1.0);
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var vs = createShaderFromElement(app.gl,"vs");
var fs = createShaderFromElement(app.gl,"fs");
app.progObject = buildProgram(app.gl,vs,fs);
gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [
// Front face
-1.0,-1.0,1.0,// Back face
-1.0,// Top face
-1.0,// Bottom face
-1.0,// Right face
1.0,// Left face
-1.0,-1.0
];
app.nPoints = positions.length / 3;
var colors = [
1,1,1
];
var loc,buffer;
// Create and copy position buffer.
loc = gl.getAttribLocation(app.progObject,"pos");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.vertexAttribPointer(loc,3,gl.FLOAT,false /*no normalization*/,0 /*stride*/,0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
// Create and copy color buffer.
loc = gl.getAttribLocation(app.progObject,"color");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER,new Float32Array(colors),gl.STATIC_DRAW);
// Look for uniforms.
app.pmLocation = gl.getUniformLocation(app.progObject,"projMatrix");
app.mmLocation = gl.getUniformLocation(app.progObject,"modelMatrix");
app.vmLocation = gl.getUniformLocation(app.progObject,"viewMatrix");
var mat4 = glMatrix.mat4;
app.projMatrix = mat4.create();
app.modelMatrix = mat4.create();
app.viewMatrix = mat4.create();
app.pcam = mat4.create();
app.mvpMatrix = mat4.create();
var near = 0.1;
mat4.perspective(app.projMatrix,Math.PI / 4.0 /*45 degrees*/,0.1,farChanged());
mat4.lookAt(app.viewMatrix,[ 15,-10],[-5,0],[0,0]);
}
function animate(time) {
var gl = app.gl;
var mat4 = glMatrix.mat4;
// converts to seconds.
var seconds = time * 1E-3;
var dtime = time - app.oldTime;
var mm1 = mat4.create();
mat4.translate(mm1,app.modelMatrix,[2,0]);
var angle = time * 0.001;
mat4.rotateY(mm1,mm1,angle);
app.oldTime = time;
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(app.pmLocation,false,app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation,mm1);
gl.uniformMatrix4fv(app.vmLocation,app.viewMatrix);
gl.drawArrays(gl.TRIANGLES,app.nPoints);
// Pour dessiner autre cube,calculer autre model matrix
// et redessiner ... gl.drawArrays(gl.TRIANGLES,app.nPoints);
var mm2 = mat4.create();
mat4.translate(mm2,[-2,0]);
mat4.rotateY(mm2,mm2,angle)
gl.uniformMatrix4fv(app.pmLocation,mm2);
gl.uniformMatrix4fv(app.vmLocation,app.nPoints);
//for the camera
var moveInAndOut = 0.1 * Math.cos(angle);
var moveLeftAndRight = 0.1 * Math.sin(angle);
app.pcam = ([moveInAndOut,moveLeftAndRight]);
// app.viewMatrix = lookAt(app.pcam,0]);
// mat4.lookAt(app.viewMatrix,app.pcam,0]);
mat4.translate(app.viewMatrix,app.viewMatrix,app.pcam);
mat4.rotateY(app.viewMatrix,0.05);
window.requestAnimationFrame(animate);
}
function fovChanged(id,value) {
console.log("FOV Angle: ",value);
var label = document.getElementById('output-fov');
label.innerHTML = value;
}
function farChanged(id,value) {
console.log("Far Plane: ",value);
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
}
function init() {
[app.can,app.gl] = getContextGL('can');
if (app.can == null || app.gl == null) {
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
app.oldTime = 0;
animate(0);
}
init();
// -----
function getContextGL(id) {
const can = document.getElementById(id);
const gl = can.getContext('webgl');
return [can,gl];
}
function createShaderFromElement(gl,id) {
const e = document.getElementById(id);
const s = gl.createShader(e.type.indexOf('vertex') >= 0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
gl.shaderSource(s,e.text);
gl.compileShader(s);
return s;
}
function buildProgram(gl,fs) {
const p = gl.createProgram();
gl.attachShader(p,vs);
gl.attachShader(p,fs);
gl.linkProgram(p);
return p;
}
div
{
}
#main-div
{
display:inline-block;
}
#viewport,#manager
{
float: left;
margin: auto;
}
.color
{
width:100px;
height:50px;
}
.blue{
background:#0f0;
}
#viewport
{
width: 600px;
height:700px;
}
#can
{
width: 600px;
height: 500px;
border:1px solid orange;
}
#manager
{
width: 200px;
height:300px;
padding: 0 0 0 5px;
}
#obj-list
{
width: 200px;
}
<!DOCTYPE html>
<html>
<head>
<title>Cube Transform</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="transforms.js"></script>
<script src="utils.js"></script>
<script src="gl-matrix-min.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
attribute vec3 pos;
attribute vec3 color;
varying vec3 fColor;
void main()
{
fColor = color;
vec4 pt = vec4(pos,1.0);
gl_Position = projMatrix * viewMatrix * modelMatrix * pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec3 fColor;
void main()
{
gl_FragColor = vec4(fColor,1);
}
</script>
</head>
<body onload="init();">
<div id="main-div">
<div id="viewport">
<canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
<div class="slider">
<span class="slider-label">FOV cam</span>
<input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id,this.value)" />
<span id="output-fov" class="slider-value">20</span>
</div>
<div class="slider">
<span class="slider-label">Far Plane</span>
<input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id,this.value)" />
<span id="output-far" class="slider-value">5</span>
</div>
</div>
</div>
</body>
</html>
我的代码包含多个文件,所以这里是完整代码的链接:
https://wetransfer.com/downloads/f05fa22faa0e0803a0b6fa13348d7d9520200920195230/52fc67
js代码在transforms.js中。
谢谢!
解决方法
此行
mat4.perspective(app.projMatrix,Math.PI / 4.0 /*45 degrees*/,1,0.1,farChanged());
没有任何意义。 farChanged
不返回任何内容。它只是设置标签的innerHTML
当事件被调用时,您需要更新项目矩阵
function farChanged(id,value) {
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
glMatrix.mat4.perspective(app.projMatrix,parseFloat(value));
}
// Application info.
var app = app || {};
function initGL() {
var gl = app.gl;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.viewport(0,app.can.width,app.can.height);
gl.clearColor(0.,0.,1.0);
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var vs = createShaderFromElement(app.gl,"vs");
var fs = createShaderFromElement(app.gl,"fs");
app.progObject = buildProgram(app.gl,vs,fs);
gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [
// Front face
-1.0,-1.0,1.0,// Back face
-1.0,// Top face
-1.0,// Bottom face
-1.0,// Right face
1.0,// Left face
-1.0,-1.0
];
app.nPoints = positions.length / 3;
var colors = [
1,1
];
var loc,buffer;
// Create and copy position buffer.
loc = gl.getAttribLocation(app.progObject,"pos");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.vertexAttribPointer(loc,3,gl.FLOAT,false /*no normalization*/,0 /*stride*/,0 /*offset*/ );
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
// Create and copy color buffer.
loc = gl.getAttribLocation(app.progObject,"color");
buffer = gl.createBuffer();
gl.enableVertexAttribArray(loc);
gl.bindBuffer(gl.ARRAY_BUFFER,new Float32Array(colors),gl.STATIC_DRAW);
// Look for uniforms.
app.pmLocation = gl.getUniformLocation(app.progObject,"projMatrix");
app.mmLocation = gl.getUniformLocation(app.progObject,"modelMatrix");
app.vmLocation = gl.getUniformLocation(app.progObject,"viewMatrix");
var mat4 = glMatrix.mat4;
app.projMatrix = mat4.create();
app.modelMatrix = mat4.create();
app.viewMatrix = mat4.create();
app.pcam = mat4.create();
app.mvpMatrix = mat4.create();
var near = 0.1;
mat4.perspective(app.projMatrix,10);
mat4.lookAt(app.viewMatrix,[15,-10],[-5,0],[0,0]);
}
function animate(time) {
var gl = app.gl;
var mat4 = glMatrix.mat4;
// converts to seconds.
var seconds = time * 1E-3;
var dtime = time - app.oldTime;
var mm1 = mat4.create();
mat4.translate(mm1,app.modelMatrix,[2,0]);
var angle = time * 0.001;
mat4.rotateY(mm1,mm1,angle);
app.oldTime = time;
gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(app.pmLocation,false,app.projMatrix);
gl.uniformMatrix4fv(app.mmLocation,mm1);
gl.uniformMatrix4fv(app.vmLocation,app.viewMatrix);
gl.drawArrays(gl.TRIANGLES,app.nPoints);
// Pour dessiner autre cube,calculer autre model matrix
// et redessiner ... gl.drawArrays(gl.TRIANGLES,app.nPoints);
var mm2 = mat4.create();
mat4.translate(mm2,[-2,0]);
mat4.rotateY(mm2,mm2,angle)
gl.uniformMatrix4fv(app.pmLocation,mm2);
gl.uniformMatrix4fv(app.vmLocation,app.nPoints);
//for the camera
var moveInAndOut = 0.1 * Math.cos(angle);
var moveLeftAndRight = 0.1 * Math.sin(angle);
app.pcam = ([moveInAndOut,moveLeftAndRight]);
// app.viewMatrix = lookAt(app.pcam,0]);
// mat4.lookAt(app.viewMatrix,app.pcam,0]);
mat4.translate(app.viewMatrix,app.viewMatrix,app.pcam);
mat4.rotateY(app.viewMatrix,0.05);
window.requestAnimationFrame(animate);
}
function fovChanged(id,value) {
console.log("FOV Angle: ",value);
var label = document.getElementById('output-fov');
label.innerHTML = value;
}
function farChanged(id,value) {
//console.log("Far Plane: ",value);
var label2 = document.getElementById('output-far');
label2.innerHTML = value;
glMatrix.mat4.perspective(app.projMatrix,parseFloat(value));
}
function init() {
[app.can,app.gl] = getContextGL('can');
if (app.can == null || app.gl == null) {
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
app.oldTime = 0;
animate(0);
}
init();
// -----
function getContextGL(id) {
const can = document.getElementById(id);
const gl = can.getContext('webgl');
return [can,gl];
}
function createShaderFromElement(gl,id) {
const e = document.getElementById(id);
const s = gl.createShader(e.type.indexOf('vertex') >= 0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
gl.shaderSource(s,e.text);
gl.compileShader(s);
return s;
}
function buildProgram(gl,fs) {
const p = gl.createProgram();
gl.attachShader(p,vs);
gl.attachShader(p,fs);
gl.linkProgram(p);
return p;
}
div {}
#main-div {
display: inline-block;
}
#viewport,#manager {
float: left;
margin: auto;
}
.color {
width: 100px;
height: 50px;
}
.blue {
background: #0f0;
}
#viewport {
width: 600px;
height: 700px;
}
#can {
width: 600px;
height: 500px;
border: 1px solid orange;
}
#manager {
width: 200px;
height: 300px;
padding: 0 0 0 5px;
}
#obj-list {
width: 200px;
}
<div id="main-div">
<div id="viewport">
<canvas id="can">Your browser doesn't seem to support canvas!</canvas>
<div class="slider">
<span class="slider-label">FOV cam</span>
<input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id,this.value)" />
<span id="output-fov" class="slider-value">20</span>
</div>
<div class="slider">
<span class="slider-label">Far Plane</span>
<input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id,this.value)" />
<span id="output-far" class="slider-value">5</span>
</div>
</div>
</div>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
attribute vec3 pos;
attribute vec3 color;
varying vec3 fColor;
void main()
{
fColor = color;
vec4 pt = vec4(pos,1.0);
gl_Position = projMatrix * viewMatrix * modelMatrix * pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying vec3 fColor;
void main()
{
gl_FragColor = vec4(fColor,1);
}
</script>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix-min.js"></script>
其他一些事情。
-
请勿使用
body onload
:https://stackoverflow.com/a/48256189/128511 -
使用the
input
event代替click
事件 -
不设置
innerHTML
,而是设置textContent
-
学习使用代码片段,以便它们起作用(请参见上面的代码片段)。特别是,您不需要
<html>
,<head>
,不存在的指向<scripts>
的链接,也不需要链接到glMatrix的CDN。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。