glArrayType = typeof Float32Array !="undefined" ? Float32Array : (typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array);
function IdentityMat44() {
var m = new glArrayType(16);
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
};
function RotateAxis(matA, angRad, axis) {
var aMap = [ [1, 2], [2, 0], [0, 1] ];
var a0 = aMap[axis][0], a1 = aMap[axis][1];
var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
var matB = new glArrayType(16);
for (var i = 0; i < 16; ++ i) matB[i] = matA[i];
for (var i = 0; i < 3; ++ i) {
matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
}
return matB;
}
function Cross(a, b) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; }
function Dot(a, b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
function Normalize(v) {
var len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
return [ v[0]/len, v[1]/len, v[2]/len ];
}
var Camera = {};
Camera.create = function() {
this.pos = [0, 3, 0.0];
this.target = [0, 0, 0];
this.up = [0, 0, 1];
this.fov_y = 90;
this.vp = [800, 600];
this.near = 0.5;
this.far = 100.0;
}
Camera.Perspective = function() {
var fn = this.far + this.near;
var f_n = this.far - this.near;
var r = this.vp[0]/this.vp[1];
var t = 1/Math.tan(Math.PI * this.fov_y/360);
var m = IdentityMat44();
m[0] = t/r; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = t; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = -fn/f_n; m[11] = -1;
m[12] = 0; m[13] = 0; m[14] = -2 * this.far * this.near/f_n; m[15] = 0;
return m;
}
Camera.LookAt = function() {
var mz = Normalize([ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ]);
var mx = Normalize(Cross(this.up, mz));
var my = Normalize(Cross(mz, mx));
var tx = Dot(mx, this.pos);
var ty = Dot(my, this.pos);
var tz = Dot([-mz[0], -mz[1], -mz[2]], this.pos);
var m = IdentityMat44();
m[0] = mx[0]; m[1] = my[0]; m[2] = mz[0]; m[3] = 0;
m[4] = mx[1]; m[5] = my[1]; m[6] = mz[1]; m[7] = 0;
m[8] = mx[2]; m[9] = my[2]; m[10] = mz[2]; m[11] = 0;
m[12] = tx; m[13] = ty; m[14] = tz; m[15] = 1;
return m;
}
var ShaderProgram = {};
ShaderProgram.Create = function(shaderList) {
var shaderObjs = [];
for (var i_sh = 0; i_sh < shaderList.length; ++ i_sh) {
var shderObj = this.CompileShader(shaderList[i_sh].source, shaderList[i_sh].stage);
if (shderObj == 0)
return 0;
shaderObjs.push(shderObj);
}
var progObj = this.LinkProgram(shaderObjs)
if (progObj != 0) {
progObj.attribIndex = {};
var noOfAttributes = gl.getProgramParameter(progObj, gl.ACTIVE_ATTRIBUTES);
for (var i_n = 0; i_n < noOfAttributes; ++ i_n) {
var name = gl.getActiveAttrib(progObj, i_n).name;
progObj.attribIndex[name] = gl.getAttribLocation(progObj, name);
}
progObj.unifomLocation = {};
var noOfUniforms = gl.getProgramParameter(progObj, gl.ACTIVE_UNIFORMS);
for (var i_n = 0; i_n < noOfUniforms; ++ i_n) {
var name = gl.getActiveUniform(progObj, i_n).name;
progObj.unifomLocation[name] = gl.getUniformLocation(progObj, name);
}
}
return progObj;
}
ShaderProgram.AttributeIndex = function(progObj, name) { return progObj.attribIndex[name]; }
ShaderProgram.UniformLocation = function(progObj, name) { return progObj.unifomLocation[name]; }
ShaderProgram.Use = function(progObj) { gl.useProgram(progObj); }
ShaderProgram.SetUniformI1 = function(progObj, name, val) { if(progObj.unifomLocation[name]) gl.uniform1i(progObj.unifomLocation[name], val); }
ShaderProgram.SetUniformF1 = function(progObj, name, val) { if(progObj.unifomLocation[name]) gl.uniform1f(progObj.unifomLocation[name], val); }
ShaderProgram.SetUniformM44 = function(progObj, name, mat) { if(progObj.unifomLocation[name]) gl.uniformMatrix4fv(progObj.unifomLocation[name], false, mat); }
ShaderProgram.CompileShader = function(source, shaderStage) {
var shaderScript = document.getElementById(source);
if (shaderScript) {
source = "";
var node = shaderScript.firstChild;
while (node) {
if (node.nodeType == 3) source += node.textContent;
node = node.nextSibling;
}
}
var shaderObj = gl.createShader(shaderStage);
gl.shaderSource(shaderObj, source);
gl.compileShader(shaderObj);
var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!status) alert(gl.getShaderInfoLog(shaderObj));
return status ? shaderObj : 0;
}
ShaderProgram.LinkProgram = function(shaderObjs) {
var prog = gl.createProgram();
for (var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh)
gl.attachShader(prog, shaderObjs[i_sh]);
gl.linkProgram(prog);
status = gl.getProgramParameter(prog, gl.LINK_STATUS);
if (!status) alert("Could not initialise shaders");
gl.useProgram(null);
return status ? prog : 0;
}
var VertexBuffer = {};
VertexBuffer.Create = function(attributes, indices) {
var buffer = {};
buffer.buf = [];
buffer.attr = []
for (var i = 0; i < attributes.length; ++ i) {
buffer.buf.push(gl.createBuffer());
buffer.attr.push({ size : attributes[i].attrSize, loc : attributes[i].attrLoc });
gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes[i].data), gl.STATIC_DRAW);
}
buffer.inx = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
buffer.inxLen = indices.length;
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
return buffer;
}
VertexBuffer.Draw = function(bufObj) {
for (var i = 0; i < bufObj.buf.length; ++ i) {
gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]);
gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(bufObj.attr[i].loc);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);
gl.drawElements(gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);
for (var i = 0; i < bufObj.buf.length; ++ i)
gl.disableVertexAttribArray(bufObj.attr[i].loc);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
function drawScene(){
var canvas = document.getElementById("billboard-canvas");
Camera.create();
Camera.vp = [canvas.width, canvas.height];
var currentTime = Date.now();
var deltaMS = currentTime - startTime;
var texUnit = 0;
gl.activeTexture(gl.TEXTURE0 + texUnit);
gl.bindTexture(gl.TEXTURE_2D, textureObj);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var rotMat = IdentityMat44();
rotMat = RotateAxis(rotMat, CalcAng(currentTime, 13.0), 0);
rotMat = RotateAxis(rotMat, CalcAng(currentTime, 17.0), 1);
var d = 1.0 + 0.7*Math.sin(CalcAng(currentTime, 25.0))
Camera.pos = [d*rotMat[0], d*rotMat[1], d*rotMat[2]];
var viewMat = Camera.LookAt();
// set up draw shader
ShaderProgram.Use(progDraw);
ShaderProgram.SetUniformM44(progDraw, "u_projectionMat44", Camera.Perspective());
ShaderProgram.SetUniformM44(progDraw, "u_viewMat44", viewMat);
ShaderProgram.SetUniformI1(progDraw, "u_texture", texUnit);
var modelMat = IdentityMat44();
modelMat[0] = 0.5; modelMat[5] = 0.5;
modelMat[12] = -0.55;
ShaderProgram.SetUniformM44(progDraw, "u_modelMat44", modelMat);
ShaderProgram.SetUniformF1(progDraw, "u_billboard", 0.0);
VertexBuffer.Draw(bufPlane);
modelMat[12] = 0.55
ShaderProgram.SetUniformM44(progDraw, "u_modelMat44", modelMat);
ShaderProgram.SetUniformF1(progDraw, "u_billboard", 1.0);
VertexBuffer.Draw(bufPlane);
}
var Texture = {};
Texture.HandleLoadedTexture2D = function(image, texture, flipY) {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
if (flipY != undefined && flipY == true)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
\t gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
}
Texture.LoadTexture2D = function(name) {
var texture = gl.createTexture();
texture.image = new Image();
texture.image.setAttribute('crossorigin', 'anonymous');
texture.image.onload = function() {
Texture.HandleLoadedTexture2D(texture.image, texture, true)
}
texture.image.src = name;
return texture;
}
var startTime;
function Fract(val) {
return val - Math.trunc(val);
}
function CalcAng(currentTime, intervall) {
return Fract((currentTime - startTime)/(1000*intervall)) * 2.0 * Math.PI;
}
function CalcMove(currentTime, intervall, range) {
var pos = self.Fract((currentTime - startTime)/(1000*intervall)) * 2.0
var pos = pos < 1.0 ? pos : (2.0-pos)
return range[0] + (range[1] - range[0]) * pos;
}
function EllipticalPosition(a, b, angRag) {
var a_b = a * a - b * b
var ea = (a_b <= 0) ? 0 : Math.sqrt(a_b);
var eb = (a_b >= 0) ? 0 : Math.sqrt(-a_b);
return [ a * Math.sin(angRag) - ea, b * Math.cos(angRag) - eb, 0 ];
}
var sliderScale = 100.0
var gl;
var progDraw;
var bufCube = {};
function sceneStart() {
var canvas = document.getElementById("billboard-canvas");
var vp = [canvas.width, canvas.height];
gl = canvas.getContext("experimental-webgl");
if (!gl)
return;
progDraw = ShaderProgram.Create(
[ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
{ source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
]);
progDraw.inPos = gl.getAttribLocation(progDraw, "inPos");
progDraw.inTex = gl.getAttribLocation(progDraw, "inTex");
if (progDraw == 0)
return;
var planPosData = [-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0];
var planTexData = [ 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 ];
var planInxData = [0,1,2,0,2,3];
bufPlane = VertexBuffer.Create(
[ { data : planPosData, attrSize : 3, attrLoc : progDraw.inPos },
{ data : planTexData, attrSize : 2, attrLoc : progDraw.inTex } ],
planInxData);
textureObj = Texture.LoadTexture2D("https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/tree.jpg");
startTime = Date.now();
setInterval(drawScene, 50);
}
<script id="draw-shader-vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec3 inPos;
attribute vec2 inTex;
varying vec2 vertTex;
uniform mat4 u_projectionMat44;
uniform mat4 u_viewMat44;
uniform mat4 u_modelMat44;
uniform float u_billboard;
void main()
{
vertTex = inTex;
float scale = u_billboard > 0.5 ? length(u_viewMat44[3].xyz) : 1.0;
mat4 scaleMat = mat4(
vec4(scale,0.0,0.0,0.0),
vec4(0.0,scale,0.0,0.0),
vec4(0.0,0.0,1.0,0.0),
vec4(0.0,0.0,0.0,1.0));
mat4 bbView = mat4(
vec4(1.0,0.0,0.0,0.0),
vec4(0.0,1.0,0.0,0.0),
vec4(0.0,0.0,1.0,0.0),
u_viewMat44[3]);
mat4 view = u_billboard > 0.5 ? bbView : u_viewMat44;
gl_Position = u_projectionMat44 * view * scaleMat * u_modelMat44 * vec4(inPos, 1.0);
}
</script>
<script id="draw-shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vertTex;
uniform sampler2D u_texture;
uniform sampler2D u_normalMap;
void main()
{
vec3 texColor = texture2D(u_texture, vertTex.st).rgb;
gl_FragColor = vec4(texColor.rgb, 1.0);
}
</script>
<body onload="sceneStart();">
<canvas id="billboard-canvas" style="border: none;" width="512" height="512"></canvas>
</body>
ohne MCVE schwer zu sagen, aber ich würde versuchen, die Verwendung von 'view * Modell 'mit Einheitsmatrix mit Ursprung in dem s eingestellt zu ändern als das 'view * model' Ergebnis hat. Das sollte abgebrochen oder gedreht werden, wenn Skalierung vorhanden ist, dann müssen Sie jede Einheitsvektorgröße so einstellen, dass sie der Größe aus dem Ergebnis entspricht ... Weitere Informationen finden Sie unter [Verständnis von homogenen 4x4-Transformationsmatrizen] (https://stackoverflow.com/a/ 28084380/2521214) – Spektre
Ich habe eine MVCE hinzugefügt – kevzettler
Ich verstehe immer noch nicht das Problem. Was stimmt nicht mit 'mat4 bbView = mat4 (vec4 (1,0,0,0,0,0,0,0), vec4 (0,0,1,0,0,0,0,0), vec4 (0,0,0,0,1,0,0,0), Ansicht [3]);' 'gl_Position = Projektion * bbView * Modell * vec4 (Position, 1);' – Rabbid76