- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于荣誉学分无关的类(class)项目,我需要使用 WebGL 来显示我选择的用作纹理的图像,然后变形纹理以使其看起来像是在以某种方式移动或变化。
为此,我选择变形雨滴纹理,使其看起来就像雨滴从屏幕上掉下来一样。我有一个风景背景纹理(一个 .jpg 图像),我想用雨滴纹理(一个 .png 图像)覆盖它,但我不确定如何覆盖背景纹理以便我可以在同时。我现在拥有的代码仅显示背景图像。
谁能帮我解释一下我做错了什么,我该如何解决这个问题?如果您需要我上传我的部分代码以查看,请告诉我。我几乎不了解 WebGL,所以我不知道要显示我的代码的哪个区域才能看到我哪里出错了。据我所知,整件事可能都是错的。
编辑:我被告知要添加代码,所以由于我不知道要显示什么片段,这里是我的整个 javascript 和 html 文件:
另请注意:此代码仅适用于 FireFox!谷歌浏览器会报错! (虽然我认为不管怎样都会报错,因为我没有给出.html文件中引用的文件)*
var canvas;
var gl;
var Index = 0;
var texCoord = [
vec2(0, 0),
vec2(0, 1),
vec2(1, 1),
vec2(1, 1),
vec2(1, 0),
vec2(0, 0)
];
var vertices = [
vec2( -1, -1 ),
vec2( -1, 1 ),
vec2( 1, 1 ),
vec2( 1, 1 ),
vec2( 1, -1 ),
vec2( -1, -1 )
];
var pointsArray = [];
//PROGRAMS
var program1; //for background
var program2; //for rain texture
var program3; //for rain texture updates
//TEXTURES
var texture1; //background image (STATIC IMAGE)
var texture2; // Raindrop texture (bounce between 2 and 3)
var texture3; // Raindrop texture (transform to be sent between 2 and 3)
//BUFFERS--------------------------------------------------------------------
var framebuffer;
var buffer1; //buffer for static background (texture1) vertices
var buffer2; //buffer for static background (texture1) texcoordinates
var buffer3; //buffer for raindrops (texture2) vertices
var buffer4; //buffer for raindrops (texture2) texcoordinates
var buffer5; //buffer for texture3 vertices
var buffer6; //buffer for texture3 texcoordinates
window.onload = function init() {
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }
//----------------------------------------------------------------------------------------------------------------------------------------
//BACKGROUND texture
texture1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture1);
// Fill the texture with a blue screen (fill canvas) FILLER!!!
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1024, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
// load image
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
// Get the IMG tag by its ID
var bgpic = document.getElementById("background");
gl.bindTexture(gl.TEXTURE_2D, texture1);
// Load data from the IMG
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bgpic);
gl.generateMipmap(gl.TEXTURE_2D);
//------------------------------------------------------------------------------------------------------------------------------------------
//RAINDROP TEXTURE
texture2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture2);
// Fill the texture with a blue screen (fill canvas) FILLER!!!
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1024, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
// load image
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
// Get the IMG tag by its ID
var rainPic = document.getElementById("raindrop");
gl.bindTexture(gl.TEXTURE_2D, texture2);
// Load data from the IMG
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, rainPic);
gl.generateMipmap(gl.TEXTURE_2D);
//------------------------------------------------------------------------------------------------------------------------------------------
//EMPTY TEXTURE TO PASS TEXTURE2 TO
texture3 = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D, texture2 );
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1024, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
//------------------------------------------------------------------------------------------------------------------------------------------
// Allocate a frame buffer object
framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
framebuffer.width = 4096;
framebuffer.height = 2048;
//------------------------------------------------------------------------------------------------------------------------------------------
// Attach color buffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
//------------------------------------------------------------------------------------------------------------------------------------------
// check for completeness
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if(status != gl.FRAMEBUFFER_COMPLETE) alert('Frame Buffer Not Complete');
//------------------------------------------------------------------------------------------------------------------------------------------
//
// Load shaders and initialize attribute buffers
//
program1 = initShaders( gl, "vertex-shader1", "fragment-shader1" );
program2 = initShaders( gl, "vertex-shader2", "fragment-shader2" );
program3 = initShaders(gl, "vertex-shader3","fragment-shader3");
//------------------------------------------------------------------------------------------------------------------------------------------
//PROGRAM 1 CODE
gl.useProgram( program1 );
gl.useProgram(program1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture1);
// send data to GPU for normal render
buffer1 = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer1);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW);
var vPosition = gl.getAttribLocation( program1, "vPosition" );
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
buffer2 = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer2);
gl.bufferData( gl.ARRAY_BUFFER, flatten(texCoord), gl.STATIC_DRAW);
var vTexCoord = gl.getAttribLocation( program1, "vTexCoord");
gl.vertexAttribPointer( vTexCoord, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vTexCoord );
gl.uniform1i( gl.getUniformLocation(program1, "texture1"), 0);
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.viewport(0, 0, 2048, 1024);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
//------------------------------------------------------------------------------------------------------------------------------------------
//PROGRAM 2 CODE
gl.useProgram(program2);
// Create and initialize a buffer object
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture2);
buffer3 = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer3 );
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program2, "vPosition" );
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
// Bind FBO and render
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.viewport(0, 0, 2048, 1024);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT );
// gl.drawArrays(gl.TRIANGLES, 0, numVertices);
// Bind to window system frame buffer, unbind the texture
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
//------------------------------------------------------------------------------------------------------------------------------------------
//PROGRAM 3 CODE
gl.useProgram(program3);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture3);
// send data to GPU for normal render
buffer5 = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer5);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW);
var vPosition = gl.getAttribLocation( program3, "vPosition" );
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
buffer6 = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer6);
gl.bufferData( gl.ARRAY_BUFFER, flatten(texCoord), gl.STATIC_DRAW);
var vTexCoord = gl.getAttribLocation( program3, "vTexCoord");
gl.vertexAttribPointer( vTexCoord, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vTexCoord );
gl.uniform1i( gl.getUniformLocation(program3, "texture2"), 0);
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.viewport(0, 0, 2048, 1024);
render();
}
function render() {
// render to texture
//------------------------------------------------------------------------------------------------------------------------------------------
// SECTION FOR BACKGROUND TEXTURE!
//BACKGROUND TEXTURE: USE PROGRAM 1
gl.useProgram(program1);
gl.clear( gl.COLOR_BUFFER_BIT );
gl.drawArrays( gl.TRIANGLES, 0, 6 );
gl.bindFramebuffer( gl.FRAMEBUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, texture1);
gl.clear( gl.COLOR_BUFFER_BIT );
gl.drawArrays(gl.TRIANGLES, 0, 6);
//------------------------------------------------------------------------------------------------------------------------------------------
//RAIN TEXTURE: USE PROGRAM 2
gl.useProgram(program2);
gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer);
if(flag) {
gl.bindTexture(gl.TEXTURE_2D, texture2);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture3, 0);
}
else {
gl.bindTexture(gl.TEXTURE_2D, texture3);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture2, 0);
}
//------------------------------------------------------------------------------------------------------------------------------------------
// RAIN TEXTURE: USE PROGRAM 3
gl.useProgram(program3);
gl.drawArrays( gl.TRIANGLES, 0, 6 );
gl.bindFramebuffer( gl.FRAMEBUFFER, null);
if(flag) gl.bindTexture(gl.TEXTURE_2D, texture2);
else gl.bindTexture(gl.TEXTURE_2D, texture2);
gl.clear( gl.COLOR_BUFFER_BIT );
gl.drawArrays(gl.TRIANGLES, 0, 6);
flag = !flag
requestAnimFrame(render);
}
<!DOCTYPE html>
<html>
<script id="vertex-shader1" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 vTexCoord;
varying vec2 fTexCoord;
void main()
{
gl_Position = vPosition;
fTexCoord= vTexCoord;
}
</script>
<script id="vertex-shader2" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 vTexCoord;
varying vec2 fTexCoord;
void main()
{
gl_Position = vPosition;
fTexCoord= vTexCoord;
}
</script>
<script id="vertex-shader3" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 vTexCoord;
varying vec2 fTexCoord;
void main()
{
gl_Position = vPosition;
fTexCoord = vTexCoord;
}
</script>
<script id="fragment-shader1" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D texture1;
varying vec2 fTexCoord;
void
main()
{
gl_FragColor= texture2D(texture1, fTexCoord);
}
</script>
<script id="fragment-shader2" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D texture2;
varying vec2 fTexCoord;
void main()
{
gl_FragColor= texture2D(texture2, fTexCoord);
}
</script>
<script id="fragment-shader3" type="x-shader/x-fragment">
precision mediump float;
varying vec2 fTexCoord;
uniform sampler2D texture2;
void main()
{
float y= fTexCoord.y - 0.1;
float x= fTexCoord.x;
if(y < 0.0) {
y = 1.0;
x = fTexCoord.x + 0.1 ;
}
if(x > 1.0){
x = 0.0;
}
gl_FragColor = texture2D( texture2, vec2(x,y));
}
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/InitShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="testingBG.js"></script>
<img src="Raindrops_scaled.png" id="raindrop" hidden />
<img src="Background.jpg" id="background" hidden />
<body>
<canvas id="gl-canvas" width="2048" height="1024">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
</body>
</html>
最佳答案
我已尝试提供更全面的解释,说明适合您的解决方案可能包含哪些内容。
由于 cors >,这在 chrome 中可能不起作用 >.>
编辑:通过手动将图像作为位图数组插入来绕过 cors。 T.T
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
img {
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
// I've only placed this here to get around cors < _ >
var images = function() {
"use strict";
function Image(width,height,pixels) {
this.width = width;
this.height = height;
this.pixels = pixels;
}
return {
background: new Image(16,16,new Uint8Array([127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,95,95,95,255,95,95,95,255,127,127,127,255,127,127,127,255,127,127,127,255,95,95,95,255,127,127,127,255,127,127,127,255,95,95,95,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,95,95,95,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,95,95,95,255,127,127,127,255,127,127,127,255,95,95,95,255,127,127,127,255,127,127,127,255,127,127,127,255,127,127,127,255,95,95,95,255,95,95,95,255,95,95,95,255,153,217,234,255,95,95,95,255,127,127,127,255,127,127,127,255,95,95,95,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,95,95,95,255,95,95,95,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,22,116,50,255,22,116,50,255,22,116,50,255,22,116,50,255,22,116,50,255,22,116,50,255,22,116,50,255,22,116,50,255,153,217,234,255,153,217,234,255,153,217,234,255,153,217,234,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255,34,177,76,255])),
raindrop: new Image(8,8,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,41,49,151,255,41,49,151,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,49,151,255,64,73,202,255,64,73,202,255,41,49,151,255,0,0,0,0,0,0,0,0,0,0,0,0,41,49,151,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,41,49,151,255,0,0,0,0,0,0,0,0,41,49,151,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,41,49,151,255,0,0,0,0,41,49,151,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,41,49,151,255,41,49,151,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,41,49,151,255,0,0,0,0,41,49,151,255,64,73,202,255,64,73,202,255,64,73,202,255,64,73,202,255,41,49,151,255,0,0,0,0,0,0,0,0,0,0,0,0,41,49,151,255,41,49,151,255,41,49,151,255,41,49,151,255,0,0,0,0,0,0,0,0]))
};
}();
void function() {
"use strict";
// Variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var gl = null;
var raindrops = [];
// WebGL programs (contains code that modifies your vertex data & code that processes each pixel)
var backgroundProgram = null;
var raindropProgram = null;
// WebGL program attributes (indexes into attributes inside the program, webgl uses these to interpret data in the buffers)
var aPositionLocation = 0;
var aUVLocation = 1;
// WebGL program uniforms (It's a variable that's shared between Javascript and the program, you just need to call a function to update it's value)
var uRaindropPosition = null; // vec2
var uRaindropSize = null; // vec2
// WebGL buffers (It's like an array '[]', but it's on the GPU, we'll use it here to specify the properties of triangles we want to draw)
var backgroundBuffer = null;
// WebGL textures
var backgroundTexture = null;
var raindropTexture = null;
// Constructors
// If this function is called with 'new Raindrop(0,0,10);' it'll create a new raindrop object that has these properties
function Raindrop(x,y,size) {
this.x = x;
this.y = y;
this.size = size;
}
// Functions
function createProgram(vertexCode,fragmentCode) {
var program = gl.createProgram();
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// Upload source code
gl.shaderSource(vertexShader,vertexCode);
gl.shaderSource(fragmentShader,fragmentCode);
// Compile shaders
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// Check there isn't any problems
try {
if (!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS)) {
throw "Vertex Shader: " + gl.getShaderInfoLog(vertexShader);
}
if (!gl.getShaderParameter(fragmentShader,gl.COMPILE_STATUS)) {
throw "Fragment Shader: " + gl.getShaderInfoLog(fragmentShader);
}
} catch(log) {
gl.deleteProgram(program);
gl.deleteShader(vertexShader);
gl.deleteShader(vertexShader);
console.error(log);
}
// Attach to the main program
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
return program;
}
function createBuffer(data) {
// Create a GPU buffer, it's a really simple object
// Buffers can be best thought of as a normal array that sits in GPU memory (VRAM)
var buffer = gl.createBuffer();
// attach our new buffer on the gpu to 'ARRAY_BUFFER'
// Think of it as, whatever is attached to 'ARRAY_BUFFER' is the current buffer that get used with WebGl functions
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
// Upload our array of verticies as 32 bit floats
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data),gl.STATIC_DRAW);
// Tell WebGL we're not using the buffer anymore at the moment
gl.bindBuffer(gl.ARRAY_BUFFER,null);
return buffer;
}
function createTexture(image) {
var texture = gl.createTexture();
// attach our new texture on the gpu to 'TEXTURE_2D'
// Think of it as, whatever is attached is our current texture we're using for webgl functions
gl.bindTexture(gl.TEXTURE_2D,texture);
// Set texture parameters, i.e. how are we going to scale it up or down/ what should happen if we
// try to get a pixel from outside the texture
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST); // Use nearest neighbour when sizing up
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST); // Use nearest neighbour when sizing down
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.REPEAT); // Apply a modulo to x coordinates if there outside the texture
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.REPEAT); // Apply a modulo to y coordinates if there outside the texture
// Upload our image to our gpu texture
gl.texImage2D(
gl.TEXTURE_2D, // I want it to get uploaded to what's attached to TEXTURE_2D
0, // Mipmap level, it can stay at 0
gl.RGBA, // Data format the gpu texture will use, in this case 8 bit RGBA for each pixel
image.width,
image.height,
0, // Border, always should be zero
gl.RGBA, // The data format of the image we're uploading to the gpu
gl.UNSIGNED_BYTE, // Datatype of each actual colour channel, here it's going to be an unsigned 8 bit int that will go from 0-255
image.pixels // The image we finally want to upload!, any HTML image element will work just fine
);
// Now we'll unbind the texture since we are done with it now
gl.bindTexture(gl.TEXTURE_2D,null); // Passing null tells WebGL that we're not currently 'using' any texture
return texture;
}
// Convert from Javascript canvas coordinate system to WebGL's normalized device coordinates
/*
The position 0,0 moves to the center of the screen.
The top left corner becomes -1,1
The bottom right corner becomes 1,-1
Coordinates need to be converted before they can be passed to WebGL
*/
function convertXCoordinate(x) {
return (x / canvasWidth) * 2.0 - 1.0;
}
function convertYCoordinate(y) {
return ((canvasHeight - y) / canvasHeight) * 2.0 - 1.0;
}
function loop() {
// Update
// Update raindrop positions
// Just to simulate rain 'falling'
for (var i = 0; i < raindrops.length; ++i) {
var raindrop = raindrops[i];
raindrop.y += 2.5;
if (raindrop.y > canvasHeight) {
raindrop.x = Math.random() * canvasWidth;
raindrop.y = 0;
}
}
// Render
// Clear the canvas
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the background
gl.bindBuffer(gl.ARRAY_BUFFER,backgroundBuffer);
// We use this function to tell WebGL how to interpret the data in the current buffer
gl.vertexAttribPointer(
aPositionLocation, // attribute index, usually just the order they were declared in the vertex shader
2, // Number of values in attribute, vec2 has two floats
gl.FLOAT, // The kind of data to be expected in the buffer
false, // Telling WebGL we don't want the data to get normalized to 0.0 -> 1.0
Float32Array.BYTES_PER_ELEMENT * 4, // This is the size of a complete vertex in bytes (2 vec2's so four floats)
Float32Array.BYTES_PER_ELEMENT * 0 // This is the 'offset', or the number of floats that come before this attribute in each vertex. aPosition comes first so it's zero
);
gl.vertexAttribPointer(
aUVLocation,
2,
gl.FLOAT,
false,
Float32Array.BYTES_PER_ELEMENT * 4,
Float32Array.BYTES_PER_ELEMENT * 2 // aUV comes second, so it's offset is two floats
);
// Tell WebGL we want to turn these attributes on for rendering
gl.enableVertexAttribArray(aPositionLocation);
gl.enableVertexAttribArray(aUVLocation);
// Attach our background texture so the sampler2D can use it
gl.bindTexture(gl.TEXTURE_2D,backgroundTexture);
// Attach our program we want to render with
gl.useProgram(backgroundProgram);
// Tell WebGL to start rendering!
gl.drawArrays(
gl.TRIANGLES, // Takes groups of 3 verticies to draw one complete triangle
0, // Start at index 0 in our buffer
6 // Use six complete verticies (whole sets of attributes) to draw 2 triangles
);
// We no longer need the background buffer, program or texture
gl.bindBuffer(gl.ARRAY_BUFFER,null);
gl.disableVertexAttribArray(aPositionLocation);
gl.disableVertexAttribArray(aUVLocation);
gl.bindTexture(gl.TEXTURE_2D,null);
gl.useProgram(null);
// Draw raindrops
// Since we're going to pass coordinates through uniforms, this can be done without a buffer
// Bind texture for sampler2D
gl.bindTexture(gl.TEXTURE_2D,raindropTexture);
// After attaching a program, we can upload values to uniforms using the values we got before from getUniformLocation()
gl.useProgram(raindropProgram);
for (var i = 0; i < raindrops.length; ++i) {
var raindrop = raindrops[i];
// Upload position
gl.uniform2f(
uRaindropPosition,
convertXCoordinate(raindrop.x),
convertYCoordinate(raindrop.y)
);
// Upload size
gl.uniform1f(
uRaindropSize,
raindrop.size
);
gl.drawArrays(gl.POINTS,0,1);
}
//
requestAnimationFrame(loop);
}
// This gets called when the page finishes loading
onload = function() {
// Get the canvas
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// Don't forget the webgl context!
gl = canvas.getContext("webgl");
// Create our program, it's made up of two smaller programs.
// One processes verticies (one whole set of attributes) & one that decides the colour of each pixel
// These smaller programs need to be created, compiled then attached to the main program
// modern Javascript has a nice feature called string templates, if we use `` instead of "" we can
// write strings that can have multiple lines!
backgroundProgram = createProgram(
` // Vertex Shader
precision lowp float;
// These values are filled from our buffer
attribute vec2 aPosition;
attribute vec2 aUV;
// Anything passed to this variable gets interpolated across any
// pixels inside our triangle
varying vec2 vUV;
void main() {
vUV = aUV;
gl_Position = vec4(aPosition,0.0,1.0);
}
`,` // Fragment shader
precision lowp float;
// Freshly interpolated value from our vertex shader
varying vec2 vUV;
// A uniform is a variable shared between webgl & javascript
// A sampler2D is a special datatype we use with texture2D
// to get a single pixel from the texture that's currently
// attached to TEXTURE_2D
uniform sampler2D uTexture;
void main() {
gl_FragColor = texture2D(uTexture,vUV);
}
`
);
raindropProgram = createProgram(
` // Vertex shader
precision lowp float;
attribute vec2 aPosition;
uniform vec2 uRaindropPosition;
uniform float uRaindropSize;
void main() {
gl_PointSize = uRaindropSize;
gl_Position = vec4(uRaindropPosition + aPosition,0.0,1.0);
}
`,` // Fragment shader
precision lowp float;
uniform sampler2D uTexture;
void main() {
gl_FragColor = texture2D(uTexture,gl_PointCoord);
// Discard the pixel if it has no alpha
if (gl_FragColor.a == 0.0) {
discard;
}
}
`
);
// Get the 'location' of uniform variables in our raindrop program
// These will be used later to upload new uniform values to the gpu
uRaindropPosition = gl.getUniformLocation(raindropProgram,"uRaindropPosition");
uRaindropSize = gl.getUniformLocation(raindropProgram,"uRaindropSize");
/*
Create and upload an array of data to the GPU,
each line contains all the attribute that make up one
vertex, here it's an x y coorinate for the position on the screen
followed by another x y coordinate for the position of the texture that
should be displayed at that corner (coordinates for textures are normally called UVs U = x, V = y)
Below is a list of verticies that make up two triangles that forms a rectangle that covers the whole screen,
triangles in WebGL should go in counter clockwise order
*/
backgroundBuffer = createBuffer([
// X Y U V
-1.0, 1.0, 0.0,0.0, // Top left
-1.0,-1.0, 0.0,1.0, // Bottom left
1.0, 1.0, 1.0,0.0, // Top right
1.0, 1.0, 1.0,0.0, // Top right
-1.0,-1.0, 0.0,1.0, // Top left
1.0,-1.0, 1.0,1.0 // Bottom right
]);
// Create & upload textures
backgroundTexture = createTexture(images.background);
raindropTexture = createTexture(images.raindrop);
// Set clearcolour, when we want an empty canvas
// R G B A
gl.clearColor(0.5,0.5,0.5,1.0);
// Create some randomly placed raindrops to simulate
for (var i = 0; i < 10; ++i) {
raindrops.push(
new Raindrop(
Math.random() * canvasWidth,
Math.random() * canvasHeight,
25.0
)
);
}
loop();
}
// Called when the page is reloading or getting closed
onunload = function() {
gl.deleteProgram(backgroundProgram);
gl.deleteProgram(raindropProgram);
gl.deleteBuffer(backgroundBuffer);
gl.deleteTexture(backgroundTexture);
gl.deleteTexture(raindropTexture);
}
}();
</script>
</body>
</html>
关于javascript - WebGL:如何将移动纹理叠加在另一个纹理之上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53355677/
一些网站说你应该通过以下方式初始化 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
我是一名优秀的程序员,十分优秀!