- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在经历this WebGL tutorial我现在所在的部分应该教您在黑色 Canvas 上绘制白色正方形。不是很令人兴奋,尤其是平淡无奇,因为我得到的只是一 block 黑色 Canvas 。
Firefox 控制台显示“WebGL2RenderingContext.attachShader 的参数 2 不是对象。” This doc for WebGL2RenderingContext
没有提及任何关于 attachShader
的内容(在 initShaders
第 4 行和第 5 行调用)。我还发现奇怪的是,函数 getShader
没有传递第三个参数,即使它是用 3 定义的。
另一个可能的问题,与 Firefox 所说的无关,可能与以下事实有关:当我尝试将着色器脚本和主脚本保存在单独的文件中时,当我打开页面时,页面上没有显示任何内容。这可能是一个问题,因为本教程使用了 2 个脚本,我必须从 github here 下载这些脚本。 .
这里是index.html,我的所有代码几乎与教程完全相同,但我让它稍微简洁一些,因为它们本质上是重新定义已经是API一部分的函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
//the two scripts from github
<script src="sylvester.js" type="text/javascript"/>
<script src="glUtils.js" type="text/javascript"/>
<script type="x-shader/x-vertex" id="shader-vs">
//vertex shader goes here
</script>
<script type="x-shader/x-fragment" id="shader-fs">
//frag shader goes here
</script>
<script type="text/javascript">
//main javascript goes here
</script>
</head>
<body onload="start()">
<canvas id="glCanvas" width="640" height="480">
Your browser doesn't appear to support the
<code><canvas></code> element.
</canvas>
</body>
主要的 JavaScript:
var canvas;
var gl;
var squareVerticesBuffer;
var mvMatrix;
var shaderProgram;
var vertexPositionAttribute;
var perspectiveMatrix;
var horizAspect = 480.0/640.0;
function setMatrixUniforms(){
var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix.flatten()));
var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten()));
}
function getShader(gl, id, type){
var shaderScript , theSource, currentChild, shader;
shaderScript = document.getElementById(id);
if(!shaderScript){
console.log("Couldn't find shader script");
return null;
}
theSource = shaderScript.text;
if(!type){
if(shaderScript.type == 'x-shader/x-fragment'){
type = gl.FRAGMENT_SHADER;
}
else if (shaderScript.type == 'x-shader/x-vertex'){
type = gl.VERTEX_SHADER;
}
else {
console.log("Shader is not of a valid type");
return null;
}
}
shader = gl.createShader(type);
gl.shaderSource(shader, theSource);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
console.log("An error occured compiling the shaders:"
+ gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function initShaders() {
var fragmentShader = getShader(gl, 'shader-fs');
var vertexShader = getShader(gl, 'shader-vs');
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log('Unable to initialize the shader program: '
+ gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.enableVertexAttribArray(vertexPositionAttribute);
}
function initBuffers(){
squareVerticesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
var vertices = [1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, -1.0, 0.0];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
function drawScene(){
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
perspectiveMatrix = makePerspective(45, 4.0/3.0, 0.1, 100.0);
//perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
mvMatrix = Matrix.I(4);
mvMatrix.x(Matrix.Translation($V([-0.0, 0.0, -6.0])).ensure4x4())
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
function start() {
var canvas = document.getElementById('glCanvas');
// Initialize the GL context
var opts = { };
gl = canvas.getContext( "webgl2", opts );
if(!gl) gl = canvas.getContext("experimental-webgl2", opts);
if(!gl) gl = canvas.getContext("webgl", opts);
if(!gl) gl = canvas.getContext("experimental-webgl", opts);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, canvas.width, canvas.height);
initShaders();
initBuffers();
setInterval(drawScene, 15);
}
顶点着色器:
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
碎片着色器:
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
最佳答案
TL;DR
gl.attachShader 并不是 WebGL 2 独有的。它是一个可从任何 WebGL 上下文中使用的函数。它用于将顶点\片段着色器与程序绑定(bind)在一起以设置渲染状态 [Link] .
为了更深入地了解本教程试图传达的内容,我在下面提供了一个示例。希望您觉得它有用。
<!doctype html>
<!-- lets the browser know that this is a HTML page -->
<html>
<head>
<!-- UTF-8 Encoding, it'll complain if you don't use this -->
<meta charset="utf-8">
<!-- Just some inlined CSS to style and center the canvas -->
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin: auto;
left: 0;
right: 0;
border: solid 3px white;
border-radius: 20px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<!--
The script "type" doesn't matter, we just want to use it to load shader source code
If it isn't labled as a valid JS type the browser won't try to execute it
-->
<script id="vertexShader" type="glShader">
precision lowp float;
attribute vec2 aPos;
void main() {
// If you are just making a square you don't need a projection matrix
// The 2D coordinates are in the range of X: -1 -> +1 Y: -1 -> + 1
gl_Position = vec4(aPos,0.0,1.0);
}
</script>
<script id="fragmentShader" type="glShader">
precision lowp float;
void main() {
gl_FragColor = vec4(1.0,1.0,1.0,1.0);
}
</script>
<script type="application/javascript">
// If you only want to draw a simple 2D shape, you don't really need to use any matricies
// -- WebGL Variables --
var canvas = null; // A reference to the canvas (It doesn't contain the canvas it just has it's address)
var gl = null; // A reference for the webGL context (You don't need to use WebGL 2)
var VBO = null; // A reference for an OpenGL buffer that I'll use to store "Vertex Data"
var program = null; // A reference to an OpenGL program, you can think of it as something similar to
// a .exe in GPU memory that contains the code from your shaders
// ---------------------
// -- Normal Variables --
var width = 320; // Size of the canvas to set (in pixels)
var height = 240;
// A "Typed" array of 32 bit floats that will contain the vertex data that'll be uploaded to the gpu in the VBO buffer
// (VBO means vertex buffer object, I.E. a buffer used to contain vertex data)
// A full vertex (all the data for one corner of a mesh) would be a complete list of attributes for the vertex shader.
// e.g.
//
// if in the vertex shader you had
// attribute vec2 pos;
// attribute vec3 colour;
//
// Then a single vertex would be a sequence of five floats that are split into these attribute values
// e.g. 50.0, 50.0, 1.0,1.0,1.0,
// would become
// pos = vec2(50.0,50.0);
// colour = vec3(1.0,1.0,1.0);
//
// The reason it's put into a "Float32Array" is so WebGL knows without having to do any checks that the
// array you just gave it is exactly a list of 32 floats
// You don't strictly need to do that as WebGL can figure out the type, its just not encouraged as it has quite the performance impact
// Only has 1 attribute -> Pos 2D Vector
// Triangles are drawn in groups of three verticies
var squareVerticies = Float32Array.from([
// Top right -> top left -> bottom right (Its best to do triangles counter clockwise, look up gl.CULL_FACE for why is this the case)
0.5, 0.5,
-0.5, 0.5,
0.5,-0.5,
// Bottom Right -> top left -> bottom left
0.5,-0.5,
-0.5, 0.5,
-0.5,-0.5
]);
// ----------------------
// Called after the page has loaded
window.onload = function() {
// Get canvas reference and set size
canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;
// get WebGL context reference
// No need to do checking, as 99% of modern browsers support WebGL
gl = canvas.getContext("webgl");
// In essence to draw your square you need to seperate things
// A program (made of a vertex and fragment shader) that will say how to render the square
// And some input data (In this case the VBO) that will be what you want to render (The coordinates of the square)
// So each one should be considered seperately and can be setup in either order
// -- Program Setup --
// Extract shader code from script tags
var vertexShaderCode = document.getElementById("vertexShader").innerHTML;
var fragmentShaderCode = document.getElementById("fragmentShader").innerHTML;
// Create references to brand new shaders in GPU memory
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// Upload shader source code
gl.shaderSource(vertexShader,vertexShaderCode);
gl.shaderSource(fragmentShader,fragmentShaderCode);
// Compile Shaders
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// This function returns true/false depending on if the shaders compiled correctly
// In this case I'm checking if either one is false, I.e. if either failed to compile
if (!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS) ||
!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS)) {
// This runs if either shader had an error
console.error(
"Vertex Shader: " + gl.getShaderInfoLog(vertexShader) + "\n" +
"Fragment Shader: " + gl.getShaderInfoLog(fragmentShader)
);
// Release shader references since we don't need them if they don't work
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
// End the function early since no rendering will work with broken shaders
return;
}
// At this point if there is no error, you have a valid vertex & fragment shader in GPU memory
// But to be able to use them the two shaders need to be linked to gether
// The "Thing" that will hold them together is called a program
// Create reference to a new program in GPU memory (GPU memory is just RAM thats physically part of the GPU, often called VRAM)
program = gl.createProgram();
// attachShader is used to link a vertex shader then a fragment shader with a new program
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
// Once you have two shaders attached linkProgram glues everything together and makes it ready for rendering
gl.linkProgram(program);
// You can now delete the shader references since the program now contains them
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
// And if you want to use different shaders, all you have to do is switch the current program
gl.useProgram(program);
// -------------------
// -- Vertex Buffer (VBO) Setup --
// this just creates a generic empty block of memory on the GPU you can use for anything!
// (These blocks are called buffers)
VBO = gl.createBuffer();
// In WebGL and OpenGL if you want to operate on peices of data in GPU memory (buffers & textures mostly)
// They aren't directly access with a variable name but you need to "bind" them to the gl context
// Think of it as having this kind of effect
// currentBuffer = VBO;
// currentBuffer.doThing()
// This looks confusing but ARRAY_BUFFER is just the name of a varialbe in WebGL
// Its a reference that is being set to the new buffer (literally just ARRAY_BUFFER = VBO)
gl.bindBuffer(gl.ARRAY_BUFFER,VBO);
// This uploads the vertex data explained earlier to the GPU
// Here ARRAY_BUFFER = VBO
// squareVerticies is the data being uploaded
// and STATIC_DRAW is a hint to WebGL, its just giving it a hint what we intend to do with the data
// all STATIC_DRAW means is that we're uploading some data we're going to use to render but we aren't going to be changing it
// WebGL uses these hints to optimize the memory layout on the GPU, it does all this for you
gl.bufferData(gl.ARRAY_BUFFER,squareVerticies,gl.STATIC_DRAW);
// -------------------------
// and that is generally all you need to do to setup for rendering
// All thats left is to make sure that the program you want to use is set and you tell
// WebGL how to feed data from the VBO (squareVerticies on the GPU)
// Into the vertex shader
// The vertex shader operates on a single vertex at a time, and a vertex in terms of data is each collection of the attributes you made in the vertex shader
// that can be taken from your VBO.
//
// E.G.
// for this setup I'm using one attribute, "attribute vec2 aPos;"
// that would mean every two floats in the array form one complete vertex
// So what I need to do is tell WebGL that data format
var posAttributeLocation = gl.getAttribLocation(program,"aPos");
gl.vertexAttribPointer(
posAttributeLocation, // The index of the attribute I'm telling you about
2, // The number of floats in that attribute (2D vector => 2 floats)
gl.FLOAT, // The type of data I'm using,
gl.FALSE, // If to normalize (You can ignore this, just keep it as false or gl.FALSE)
2 * Float32Array.BYTES_PER_ELEMENT, // The total size of a complete vertex in bytes (it's the number of floats of all the attributes combined * The size of a float in bytes (4 bytes) )
0 * Float32Array.BYTES_PER_ELEMENT // The offset in bytes that this attribute is at from the beginning of a vertex
); // E.G. a float attribute thats after a 2D vector attribute would have an offset of 2 * Float32Array.BYTES_PER_ELEMENT = 8 bytes
// The last step per attribute is to tell WebGL to "turn on" use of this attribute
gl.enableVertexAttribArray(posAttributeLocation);
// Repeating that process for each attribute will tell WebGL how to send the data to your vertex shader
// This is also called setting up the buffers state
// It's also worthy to keep in mind that when you bind a different buffer you will need to repeat this step, because until you repeat your calls to vertexAttribPointer.
// Your vertex shader will still receive data from the previous buffer
// Set RGBA value for the background color
gl.clearColor(0.5,0.5,0.5,1.0);
// Clears the canvas with the colour you gave
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw using triangles from index 0 in the buffer to index 6 (With triangles it must be a factor of 3)
gl.drawArrays(gl.TRIANGLES,0,6);
}
// Called when the page is about to close
// Here I'll let go off the resources I asked WebGL to get on the GPU
window.onbeforeunload = function() {
gl.deleteProgram(program);
gl.deleteBuffer(VBO);
gl = null;
}
</script>
</body>
</html>
关于javascript - 什么是 WebGL2RenderingContext.attachShader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45655091/
一些网站说你应该通过以下方式初始化 webgl: var gl = c.getContext("webgl") || c.getContext("experimental-webgl"); if (!
我一直在寻找有关 WebGL 的信息以及可以分配用于渲染的最大纹理数/内存量。这显然是特定于硬件/设备的,因此我正在寻找一种智能处理纹理的方法。 我目前有 512x512 RGBA8 格式的纹理。一个
我想知道是否可以利用WebGL进行任何异步调用? 我研究了Spec v1和Spec v2,他们什么都没提及。在V2中,有一种WebGL查询机制,我认为这不是我想要的。 在网络上进行搜索并没有确定的定义
我正在参与一个 webgl 项目。 当我调用 gl.DrawElements 时,会显示错误“范围超出缓冲区范围”。 我肯定确保我传递了正确的缓冲区长度或偏移量。但是,仍然显示错误。 我认为有几个原因
我知道 WebGL 中有 8 个纹理的限制。 我的问题是,8 是全局限制还是每个着色器/程序明智的? 如果它是每个着色器/程序明智的限制,这是否意味着,一旦我将纹理加载到一个着色器的制服上,我就可以开
我一直在使用 Haxe + Away3D 编写一个小型行星生成器,并将其部署到 HTML5/WebGL。但是在渲染云时我遇到了一个奇怪的问题。我有行星网格,然后云网格在相同位置稍大一些。 我正在使用柏
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
在 OpenGL 中,深度缓冲区值是根据场景的近和远裁剪平面计算的。 (引用:Getting the true z value from the depth buffer) 这在 WebGL 中是如何
简单的问题,但我无法在任何地方的规范中找到答案。我可能在某处遗漏了明显的答案。 我可以在 WebGL 片段着色器中同时使用多少个纹理?如果它是可变的,那么假设 PC 使用的合理数字是多少? (对移动不
我有一个渲染场景的帧缓冲区,现在我想将它渲染到“全屏”四边形。如何设置我的相机以及我应该在我的顶点着色器中放置什么以便将帧缓冲区的纹理渲染到整个屏幕。 我试过像这样创建一个全屏四边形 var gl =
我正在阅读 here 的教程。 var gl; function initGL() { // Get A WebGL context var canvas = document.getEle
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在学习 WebGL,我能感觉到我的速度很慢,因为我很难调试我的代码。是否有任何扩展或工具可以帮助我知道缓冲区、属性指针、矩阵等的值。 我在谷歌上搜索并了解了 chrome 扩展程序 spector
我可以在某处找到任何文档来记录 WebGL 调用所需的先决条件吗? 我已经对 WebGL 基础有了相当深入的了解,但现在我正在创建自己的“框架”,并且我正在更深入地了解。 例如, enableVert
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 7年前关闭。 Improve t
我有兴趣在 webgl 中执行一些密集计算,所以它在 GPU 上运行。 大多数文档都讨论了如何渲染图形。 我正在完成非常简单的任务:对于给定的图像,将其转换为灰度,并找到局部最大值的坐标(比其邻居更亮
我目前在 WebGL 中使用这个片段着色器来对照片纹理应用高光/阴影调整。 着色器本身是直接从优秀的 GPUImage 中拉出来的适用于 iOS 的库。 uniform sampler2D input
我是 webgl 的新手。我正在尝试设置时间统一,因此我可以随着时间的推移更改片段着色器的输出。我认为这实现起来相当简单,但我正在努力。我知道这两种方法可能涉及: https://developer.
我正在尝试使用两个 Canvas 并排绘制相同的 WebGL 场景。是否可以?到目前为止,我还没有走运。 思路如下: 我加载几何 我设置了两个gl上下文,每幅 Canvas 一个 我调用 drawEl
我正在学习 WebGL 并尝试显示一个球体。没有纹理,只有每个顶点着色,但我在 Opera 和 Chrome 中收到以下错误消息:“[.WebGLRenderingContext]GL 错误:GL_I
我是一名优秀的程序员,十分优秀!