如何解决使用Webgl创建三角形的随机位置
我刚刚开始学习webgl,我一直在尝试使用javascript生成具有随机大小和位置的三角形,就像这张图片一样。
我知道我需要在函数initScene()中使用for循环,但是我不确定如何将新位置放入数组中。请帮忙。
// Application info.
var app = app || {};
var nbTriangles=20;
function getContextGL(canvasElement)
{
var can = document.getElementById(canvasElement);
if(can == null)
{
return [null,null];
}
var gl = can.getContext("webgl");
return [can,gl];
}
function createShaderFromElement(gl,id)
{
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt)
{
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment")
{
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (scriptElt.type == "x-shader/x-vertex")
{
shaderObj = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj,scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj,gl.COMPILE_STATUS);
if (!ok)
{
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl,vertexShader,fragmentShader)
{
if (!vertexShader || !fragmentShader)
{
return null;
}
var progObject = gl.createProgram();
if(!progObject)
{
alert("Can't create program object.");
return ;
}
gl.attachShader(progObject,vertexShader);
gl.attachShader(progObject,fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject,gl.LINK_STATUS);
if(!ok)
{
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL()
{
app.gl.viewport(0,app.can.width,app.can.height);
app.gl.clearColor(0.,0.,1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl,"vs");
var fs = createShaderFromElement(app.gl,"fs");
app.progObject = buildProgram(app.gl,vs,fs);
app.gl.useProgram(app.progObject);
}
function initScene()
{
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
/* Drawing one triangle:
var positions = [
// coordonnees normalisees.
0.0,0.1,-0.1,-0.1
];*/
for (var i=0; i<nbTriangles;++i)
{
var orig = [0.0,1.0,-1.0,-1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6,Math.random * 1.6];
P0 = orig[0] * scale + Trans[0];
P1 = orig[1] * scale + Trans[1];
P2 = orig[2] * scale + Trans[2];
var positions= new Positions (P0,P1,P2)
TRIANGLES.push(newPositions);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject,"pos");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER,posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation,2,gl.FLOAT,false /*no normalization*/,0 /*stride*/,0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
}
function render()
{
var gl = app.gl;
gl.clear( gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES,3* nbTriangles);
}
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();
render();
}
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>Colored Quad</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="colored_quad.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
void main()
{
vec4 pt = vec4(pos,0.0,1.0);
gl_Position = pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
void main()
{
gl_FragColor = vec4(1,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>
</div>
</body>
</html>
解决方法
运行代码时,出现错误“位置未定义”
也许您应该在发布问题之前尝试解决这些错误?如果您只是在学习JavaScript,也许these lessons would help
无论如何,此代码
Positions
有很多基本的javascript问题。
TRIANGLES
未定义(运行它时的第一个错误)。仅查看代码,我还可以看到对未定义的newPositions
的引用,对未定义的P0
的引用。我还看到P1
,P2
和orig
被假定为点,但是它们在P2
中仅引用一个值,而不是2个值( x和y)。并且Trans[2]
引用的 var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0,1.0,-1.0,-1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6,Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],orig[1] * scale + Trans[1],];
var P1 = [
orig[2] * scale + Trans[0],orig[3] * scale + Trans[1],];
var P2 = [
orig[4] * scale + Trans[0],orig[5] * scale + Trans[1],];
positions.push(...P0,...P1,...P2);
}
不存在。
这是一个解决方法
orig
另一种解决方法是遍历 for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0,Math.random() * 1.6];
for (var j = 0; j < orig.length; j += 2) {
positions.push(
orig[j ] * scale + Trans[0],orig[j + 1] * scale + Trans[1],);
}
}
中的点
const addV = (v1,v2) => v1.map((v1Elem,i) => v1Elem + v2[i]);
const scaleV = (v,scale) => v.map((elem) => elem * scale);
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0,Math.random() * 1.6];
for (var j = 0; j < orig.length; j += 2) {
// pull out 2 values from orig
let p = orig.slice(j,j + 2);
p = scaleV(p,scale);
p = addV(p,Trans);
positions.push(...p);
}
}
另一种方法是编写缩放和添加向量的函数
// Application info.
var app = app || {};
var nbTriangles = 20;
function getContextGL(canvasElement) {
var can = document.getElementById(canvasElement);
if (can == null) {
return [null,null];
}
var gl = can.getContext("webgl");
return [can,gl];
}
function createShaderFromElement(gl,id) {
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt) {
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment") {
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
} else if (scriptElt.type == "x-shader/x-vertex") {
shaderObj = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj,scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj,gl.COMPILE_STATUS);
if (!ok) {
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl,vertexShader,fragmentShader) {
if (!vertexShader || !fragmentShader) {
return null;
}
var progObject = gl.createProgram();
if (!progObject) {
alert("Can't create program object.");
return;
}
gl.attachShader(progObject,vertexShader);
gl.attachShader(progObject,fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject,gl.LINK_STATUS);
if (!ok) {
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL() {
app.gl.viewport(0,app.can.width,app.can.height);
app.gl.clearColor(0.,0.,1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl,"vs");
var fs = createShaderFromElement(app.gl,"fs");
app.progObject = buildProgram(app.gl,vs,fs);
app.gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0,-1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6,Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],];
var P1 = [
orig[2] * scale + Trans[0],];
var P2 = [
orig[4] * scale + Trans[0],];
positions.push(...P0,...P2);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject,"pos");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER,posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation,2,gl.FLOAT,false /*no normalization*/,0 /*stride*/,0 /*offset*/ );
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
}
function render() {
var gl = app.gl;
gl.clear(gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES,3 * nbTriangles);
}
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();
render();
}
init();
关于为每个三角形添加不同的颜色,我建议您阅读一些other articles on WebGL
#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>
</div>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
void main()
{
vec4 pt = vec4(pos,0.0,1.0);
gl_Position = pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
void main()
{
gl_FragColor = vec4(1,1);
}
</script>
{{1}}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。