英文:
GLSL store recurrent data in constant arrays
问题
我对着色器还不太了解,有些地方不太清楚哪些是可行的,哪些不是。例如,我有一个3D像素地形。每个顶点都有三个信息:它的位置、颜色和法线。位置对于每个顶点来说几乎是唯一的,但只有6个可能的法线,分别是左、右、上、下、前、后,以及我游戏中的256种不同颜色。因此,我尝试在顶点着色器中创建一个常量数组,将这6个法线放入其中,然后不是使用3个字节来存储每个顶点的法线,而是只使用1个字节来存储索引以进行查找。然而,这行不通,因为数组索引只能是常量。我还尝试测试如果法线等于0,那么值就是normals[0],依此类推,但这也没有成功。
我的问题是:我如何存储重复数据,然后通过在缓冲区中存储索引来检索它,而不是存储实际数据?
编辑:
我忘了提及我遇到的行为:
当将“in”变量作为数组索引传递时,它会自动转换为索引0,而当测试“in”的值并分配正确的索引时,到处都会出现奇怪的伪影。
```glsl
#version 400
const vec4 normals[6] = (vec4(1,0,0,0),....)
in int normal;
void main(void) {
// 总是返回数组的第一个元素
normals[normal]
}
编辑2:
在将glVertexAttribPointer
更改为glVertexAttribIPointer
之后,虽然我仍然有很大的伪影问题,但我将发布代码和结果:
用于创建法线VBO的方法:
private void storeDataInAttributeList(int attributeNumber, int coordsSize, byte[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
ByteBuffer buffer = storeDataInByteBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL30.glVertexAttribIPointer(attributeNumber, coordsSize, GL11.GL_BYTE, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
顶点着色器:
#version 400 core
const vec4 normals[] = vec4[6](vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(-1,0,0,0),vec4(0,-1,0,0),vec4(0,0,-1,0));
in vec3 position;
in vec3 color;
in int normal;
out vec4 color_out;
out vec3 unitNormal;
out vec3 unitLightVector;
out vec3 unitToCameraVector;
out float visibility;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
uniform float fogDensity;
uniform float fogGradient;
void main(void) {
vec4 worldPosition = transformationMatrix * vec4(position, 1.0);
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam;
color_out = vec4(color, 0.0);
unitNormal = normalize((transformationMatrix * normals[normal]).xyz);
unitLightVector = normalize(lightPosition - worldPosition.xyz);
unitToCameraVector = normalize((inverse(viewMatrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - worldPosition.xyz);
visibility = clamp(exp(-pow(length(positionRelativeToCam.xyz) * fogDensity, fogGradient)), 0.0, 1.0);
}
结果:
最终编辑:我忘记将顶点数组的大小从3更改为1,所以现在一切都正常了。
<details>
<summary>英文:</summary>
I'm pretty new to shaders and I have trouble understanding what can be done what cannot. For example, I have a 3d voxel terrain. Each vertex has 3 info: its position, its color, and its normal. The position is pretty much unique to each vertex, but they are only 6 normals possible, left right up down forward backward, and 256 different colors in my game. So I tried to create a const array in my vertexShader and put the 6 normals in there and then instead of using 3 bytes for each vertex to store the normals only using 1 to store the index to look at. However, this is not working because arrays indices can only be constant. I also tried to test if the normal = 0 then the value is normals[0], etc.. butit didn't work either.
My question is: How can I store recurrent data, and then retrieve it by storing indices in my buffers instead of the said data?
EDIT:
I forgot to mention what behavior I have:
when passing a "in" variable as an index for the array this is automatically converted to the 0 index, and when testing the value of the "in" and assigning the correct index, I have strange artifacts everywhere.
```glsl
#version 400
const vec4 normals[6](vec4(1,0,0,0),....)
in int normal;
void main(void){
normals[normal] ---> always returning the first element of the array
}
EDIT 2:
So after changing glVertexAttribPointer to glVertexAttribIPointer, I still have big artifacts so I'll post the code and the result:
Method called to create the normals vbo:
private void storeDataInAttributeList(int attributeNumber, int coordsSize,byte[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,vboID);
ByteBuffer buffer = storeDataInByteBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL30.glVertexAttribIPointer(attributeNumber, coordsSize, GL11.GL_BYTE, 0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
Vertex shader:
#version 400 core
const vec4 normals[] = vec4[6](vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(-1,0,0,0),vec4(0,-1,0,0),vec4(0,0,-1,0));
in vec3 position;
in vec3 color;
in int normal;
out vec4 color_out;
out vec3 unitNormal;
out vec3 unitLightVector;
out vec3 unitToCameraVector;
out float visibility;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
uniform float fogDensity;
uniform float fogGradient;
void main(void){
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam;
color_out = vec4(color,0.0);
unitNormal = normalize((transformationMatrix * normals[normal]).xyz);
unitLightVector = normalize(lightPosition - worldPosition.xyz);
unitToCameraVector = normalize((inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz);
visibility = clamp(exp(-pow(length(positionRelativeToCam.xyz)*fogDensity,fogGradient)),0.0,1.0);
}
Result:
Final Edit: I forgot changing the size of the vertexarray from 3 to 1 so now everything works fine
答案1
得分: 1
具有整数数据类型的顶点属性,您需要使用glVertexAttribIPointer
(注意I
),而不是glVertexAttribPointer
。请参阅glVertexAttribPointer
。属性的类型不由_type_参数指定。_type_参数只是指定源数据数组的类型。由glVertexAttribPointer
指定的属性数据会被转换为浮点数。
英文:
A vertex attribute with an integral data type has you specify glVertexAttribIPointer
(focus on I
) rather than glVertexAttribPointer
. See glVertexAttribPointer
.
The type of the attribute is not specified by the type argument. The type argument just specifies the type of the source data array. Attribute data specified by glVertexAttribPointer
is converted to floating point.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论