OpenGL Grass渲染

时间:2015-09-01 10:37:23

标签: opengl geometry-instancing

我一直在研究渲染草的不同技术。我决定使用Geometry着色器生成草,因此当我将它们渲染为GL_POINTS时,我可以动态生成三角形扇形但我没有看到我希望看到的性能。我可能会得到20-50 fps的10万片草叶,而且我有一个不错的GPU。我想知道我的方法是否错误,或者我是否达到了我的GPU的限制或者我是否正在做错误的事情,或者可能是因为它们是更快的方式(我的目标是单个刀片,我可以理想地操纵顶点) 。纹理我使用256x256

我的渲染步骤是:

创建VAO和VBO并存储位置和绑定一次:

   float[] GrassLocations= new float[100000];
   int vaoID = createVAO();
 . //bind VBO to VAO
   storeDataInAttributeList(0, 3, GrassLocations,0,0);

然后渲染:

    GL30.glBindVertexArray(VAO);
    GL20.glEnableVertexAttribArray(0);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
    GL11.glDrawArrays(GL11.GL_POINTS, 0, 100000);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);

然后我的顶点着色器:

#version 400


layout (location = 0) in vec3 VertexLocation;


uniform float time;

out vec3 offsets;
out vec3 Position;
out vec3 Normal;
out vec2 TexCoord;
out float visibility;

uniform mat4 transformationMatrix;

uniform mat4 viewMatrix;
uniform mat4 MVPmatrix;
uniform mat4 modelViewMatrix;

const float density = .007;
const float gradient = 1.5;
out float Time;

void main()
{
Time = time;

vec4 worldPosition = transformationMatrix * vec4(VertexLocation,1.0);
vec4 positionRelativeToCam = modelViewMatrix* vec4(VertexLocation,1.0); 

Normal = vec3(0,1,0);
Position = vec3(  worldPosition );

gl_Position = MVPmatrix* vec4(VertexLocation,1.0);

float distance = length(positionRelativeToCam.xyz);
visibility = exp(-pow((distance * density), gradient));
visibility = clamp(visibility,0.0,1.0);
offsets = offset;


}

我做了顶点着色器,并且只留下了GL_POSITION,但仍然没有问题。 我的几何着色器:

#version 400

layout( points ) in;
layout( triangle_strip, max_vertices = 10 ) out;

float Size2=1;   // Half the width of the quad



in vec3 Position[];
in vec3 Normal[];
in vec3 offsets[];

out vec3 position;
out vec3 normal;
in float Time[];

out vec2 TexCoord;
out vec3 color;
const  float width = 5;
void main()
{
position = Position[0];
normal = Normal[0];

color = offsets[0];

gl_Position =  (vec4(-Size2*width,-Size2,0.0,0.0) + gl_in[0].gl_Position);
TexCoord = vec2(0.0,0.0);
EmitVertex();

gl_Position =  (vec4(Size2*width,-Size2,0.0,0.0) + gl_in[0].gl_Position);
TexCoord = vec2(1.0,0.0);
EmitVertex();

gl_Position = (vec4(-Size2*width+(Time[0].x),10,0.0,0.0) + 
gl_in[0].gl_Position);
TexCoord = vec2(0.0,.25);
EmitVertex();

gl_Position = (vec4(Size2*width+(Time[0].x),10,0.0,0.0) + 
gl_in[0].gl_Position);
TexCoord = vec2(1.0,.25);
EmitVertex();
///////////////////////////////////////////////////
gl_Position =  (vec4(-Size2*width+(Time[0].x)*2,15,0.0,0.0) +   
gl_in[0].gl_Position);
TexCoord = vec2(0.0,.50);
EmitVertex();
gl_Position =  (vec4(Size2*width+(Time[0].x)*2,15,0.0,0.0) +   
gl_in[0].gl_Position);
TexCoord = vec2(1.0,.50);
EmitVertex();   
///////////////////////////////////////////////////
gl_Position =  (vec4(-Size2*width+(Time[0].x)*3,25,0.0,0.0) + 
gl_in[0].gl_Position);
TexCoord = vec2(0.0,.75);
EmitVertex();

 gl_Position =  (vec4(Size2*width+(Time[0].x)*3,25,0.0,0.0) + 
gl_in[0].gl_Position);
TexCoord = vec2(1.0,.75);
EmitVertex();  
 ///////////////////////////////////////////////////
gl_Position =  (vec4(-Size2*width,Size2*7,Time[0].x,0.0) +   
gl_in[0].gl_Position);
TexCoord = vec2(0.0,1.0);
EmitVertex();

gl_Position = (vec4(Size2*width,Size2*7,Time[0].x,0.0) +     
gl_in[0].gl_Position);
TexCoord = vec2(1.0,1.0);
EmitVertex();    
}

和我的片段Shader :(这是一个延迟引擎,我已经尝试了前向渲染,我不认为性能命中就在这里)

#version 400

in vec2 TexCoord;

layout (binding=0) uniform sampler2D SpriteTex;
in vec3 color;
in vec3 normal;
in vec3 position;
layout( location = 0 ) out vec4 FragColor;

void main() {
vec4 texColor =  texture(SpriteTex,TexCoord);
vec4 posColor = vec4(position.xyz,0);


gl_FragData[1] =  posColor;
gl_FragData[2] =  vec4(normal,1);


if(texColor.a<.5){
discard;
}


gl_FragData[0] = texColor;

}

1 个答案:

答案 0 :(得分:3)

你想要的是一种名为Instancing的技术。我链接的教程非常适合搞清楚如何进行实例化。

我可能会建议你避免使用几何着色器(因为几何着色器通常不能很好地缩放它的目的是扩展顶点的数量),而只是定义一个包含绘制一个所需顶点的缓冲区。单叶(或补丁)的草,然后使用实例重绘该对象数千次。