약간의 손실이 있습니다. 다른 정점에 다른 텍스처를 설정하려고합니다. WebGL은이 작업을 매우 불필요하게 어렵게 만듭니다. 기본적으로 원하는 꼭지점의 행렬이있는 텍스트 파일이 있습니다. (예 : http://jdmdev.net/Foundation/index.html)여러 텍스처를 제공하는 여러 셰이더 프로그램
하지만 지금은 다른 질감을 설정하기 위해 'texture atlassing'이라는 무언가를해야합니다. 온라인으로 구현하는 방법에 관한 문서는 절대적으로 없습니다.
나는 WebGL에 매우 익숙하지만 광범위한 프로그래밍 배경을 가지고있어서 나에게 주어진 어떤 개념을 이해할 수있다. 만약 내가 뭔가를보고 있거나 적어도 약간의 문서를 볼 수 있다면.
그래서 질감 아트지가 그림에서 빠져 있다고 생각합니다. 그러나, 나는 WebGL 파이프 라인을 understadning하는 경우뿐만 아니라 나는 생각합니다. 셰이더/버텍스 프로그램을 여러 개 만들 수 없습니까? 그렇다면 어떻게 할 수 있습니까? 나는 직접적인 예제가 필요하지 않지만, 단지 몇몇 코드는 놀라운 일을 할 것이다. 나는 이것을 한 번보아야 만하고 얻을 것이다. 그러나 이것은 매우 새롭기 때문에 웹상에서 유용한 물건을 찾는 것은 불가능하다. 주어진 도움을 주셔서 감사합니다.
코드는이 질문에 대답에 도움이되지만 여기에 내가 기본적으로 그래서 learningwebgltutorials.com
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform sampler2D uSampler2;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec2 vTextureCoord;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
<script id="shader2-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform sampler2D uSampler2;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script>
<script id="shader2-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec2 vTextureCoord;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
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)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
}
function handleLoadedTexture(texture) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}
var mudTexture;
var rockTexture;
function initTexture() {
mudTexture = gl.createTexture();
mudTexture.image = new Image();
mudTexture.image.onload = function() {
handleLoadedTexture(mudTexture)
}
mudTexture.image.src = "mud.gif";
rockTexture = gl.createTexture();
rockTexture.image = new Image();
rockTexture.image.onload = function() {
handleLoadedTexture(rockTexture)
}
rockTexture.image.src = "rockstar.gif";
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
return degrees * Math.PI/180;
}
var currentlyPressedKeys = {};
function handleKeyDown(event) {
currentlyPressedKeys[event.keyCode] = true;
}
function handleKeyUp(event) {
currentlyPressedKeys[event.keyCode] = false;
}
var pitch = 0;
var pitchRate = 0;
var yaw = 0;
var yawRate = 0;
var xPos = 10;
var yPos = 0.4;
var zPos = 10;
var speed = 0;
function handleKeys() {
if (currentlyPressedKeys[33]) {
// Page Up
pitchRate = 0.1;
} else if (currentlyPressedKeys[34]) {
// Page Down
pitchRate = -0.1;
} else {
pitchRate = 0;
}
if (currentlyPressedKeys[37] || currentlyPressedKeys[65]) {
// Left cursor key or A
yawRate = 0.1;
} else if (currentlyPressedKeys[39] || currentlyPressedKeys[68]) {
// Right cursor key or D
yawRate = -0.1;
} else {
yawRate = 0;
}
if (currentlyPressedKeys[38] || currentlyPressedKeys[87]) {
// Up cursor key or W
speed = 0.01;
} else if (currentlyPressedKeys[40] || currentlyPressedKeys[83]) {
// Down cursor key
speed = -0.01;
} else {
speed = 0;
}
}
var worldVertexPositionBuffer = null;
var worldVertexTextureCoordBuffer = null;
function handleLoadedWorld(data) {
var lines = data.split("\n");
var vertexCount = 0;
var vertexPositions = [];
var vertexTextureCoords = [];
for (var i in lines) {
var vals = lines[i].replace(/^\s+/, "").split(/\s+/);
if (vals.length == 6 && vals[0] != "//") {
// It is a line describing a vertex; get X, Y and Z first
vertexPositions.push(parseFloat(vals[0]));
vertexPositions.push(parseFloat(vals[1]));
vertexPositions.push(parseFloat(vals[2]));
//document.write(vertexPositions[0]);
// And then the texture coords
vertexTextureCoords.push(parseFloat(vals[3]));
vertexTextureCoords.push(parseFloat(vals[4]));
//document.write(vals[4]) + "<br/>");
vertexCount += 1;
}
}
worldVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW);
worldVertexPositionBuffer.itemSize = 3;
worldVertexPositionBuffer.numItems = vertexCount;
worldVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexTextureCoords), gl.STATIC_DRAW);
worldVertexTextureCoordBuffer.itemSize = 2;
worldVertexTextureCoordBuffer.numItems = vertexCount;
document.getElementById("loadingtext").textContent = "";
}
function loadWorld() {
var request = new XMLHttpRequest();
request.open("GET", "world.txt");
request.onreadystatechange = function() {
if (request.readyState == 4) {
handleLoadedWorld(request.responseText);
}
}
request.send();
}
function loadTextureValues() {
var request = new XMLHttpRequest();
request.open("GET", "world.txt");
request.onreadystatechange = function() {
if (request.readyState == 4) {
getCorrectTexture(request.responseText);
}
}
request.send();
}
var matchWithTexture = {};
function getCorrectTexture(data)
{
var lines = data.split("\n");
var vertexCount = 0;
var vertexTextureValueCoords = [];
for (var i in lines) {
var vals = lines[i].replace(/^\s+/, "").split(/\s+/);
if (vals.length == 6 && vals[0] != "//")
{
//document.write(vertexTextureValueCoords.push(parseFloat(vals[1])) + "</br>");
vertexTextureValueCoords.push(parseFloat(vals[5]));
matchWithTexture[vertexCount] = vertexTextureValueCoords[vertexCount];
vertexCount++;
}
}
}
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (worldVertexTextureCoordBuffer == null || worldVertexPositionBuffer == null) {
return;
}
mat4.perspective(45, gl.viewportWidth/gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
mat4.translate(mvMatrix, [-xPos, -yPos, -zPos]);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, mudTexture);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, rockTexture);
loadTextureValues();
for(var key in matchWithTexture)
{
//document.write(matchWithTexture[key] + "<br/>");
if(matchWithTexture[key] == 1)
{
gl.uniform1i(shaderProgram.samplerUniform, 0);
}
else {
gl.uniform1i(shaderProgram.samplerUniform, 1);
}
}
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, worldVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, worldVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, worldVertexPositionBuffer.numItems);
}
var lastTime = 0;
// Used to make us "jog" up and down as we move forward.
var joggingAngle = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
if (speed != 0) {
xPos -= Math.sin(degToRad(yaw)) * speed * elapsed;
zPos -= Math.cos(degToRad(yaw)) * speed * elapsed;
joggingAngle += elapsed * 0.6; // 0.6 "fiddle factor" - makes it feel more realistic :-)
yPos = Math.sin(degToRad(joggingAngle))/20 + 0.4
}
yaw += yawRate * elapsed;
pitch += pitchRate * elapsed;
}
lastTime = timeNow;
}
function tick() {
requestAnimFrame(tick);
handleKeys();
drawScene();
animate();
}
function webGLStart() {
var canvas = document.getElementById("lesson10-canvas");
initGL(canvas);
initShaders();
initTexture();
loadWorld();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
document.onkeydown = handleKeyDown;
document.onkeyup = handleKeyUp;
tick();
}
</script>
에서 사용 내 코드의 얼마나 확실하지 내가 제 2의 쉐이더/정점 프로그램을 작성하고 있었다 않은 모든 여전히 작동합니다. 그렇다면 첫 번째 쉐이더/버텍스 프로그램과는 다른 정보로 어떻게 구현할 수 있습니까?
그리고 마지막 질문은 다음과 같습니다. webgl의 모든 것을 시도하는 대신 라이브러리를 사용하는 것이 더 가치가 있습니까? 내 말은, webgl에서 수행 한 모든 Google 검색을 통해 대부분의 예제/자습서는 모두 three.js 또는 babylon.js..etc를 사용하여 완료됩니다. 내가하고있는 일을하려고 할 가치가 있는지 궁금해. 나는 질문이 무엇이겠습니까, 전문적인 설정은 내가 webgl을 똑바로 해 주길 바랄 것입니까, 아니면 (가장 가능성이 높은) 라이브러리를 사용하고 싶습니까? 나는 webgl을 프로그래밍하는 계획조차하지 않고 단지 인터뷰에서 나올지 안다. 이미 정점과 텍스처 좌표에 대한 텍스트 파일에서 정보를 파싱 된 이후, 수있는 방법이 있어야한다
https://github.com/jordmax12/WebGL/blob/master/Foundation%205/foundation_2.js
NO 텍스처 별명 VIA
솔루션은 (텍스처 자체에 대해이 작업을 수행하는 텍스처 앨리어싱없이).
[6면으로 큐브를 텍스처링하는 방법을 설명하는이 페이지의 아래쪽에 텍스처 아트 레이싱의 간단한 예가 있습니다.] (http://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html). 텍스처 좌표를 사용하여 어느 정점에 대한 텍스처 맵의 부분을 선택합니다. 따라서 모든 삼각형은 텍스처의 다른 부분을 선택할 수 있습니다. 두 인접한 삼각형이 서로 다른 질감을 사용하면 삼각형이 꼭지점을 공유하지 않는다는 것을 의미합니다. 정점은 위치 좌표와 텍스처 좌표로 구성되며 텍스 좌표는 서로 다르기 때문에 꼭지를 공유 할 수 없기 때문입니다. – gman
@gman 멋지다! 실제로 나는 간단한 텍스트 파일을 파싱하는 방법을 알아 냈고, 텍스처링을 atlasing하지 않고도 바인딩하도록했습니다. 누구든지이 작업을 원한다면 내 질문에 링크를 게시 할 것입니다. 나는 그것이 훨씬 더 쉽고, 더 '프로그래밍 적'이라고 느낀다. –