2015-09-01 6 views
1

Я изучал различные методы рендеринга травы. Я решил пойти с шейдером Geometry, создающим траву, главным образом, поэтому я могу генерировать поклонников треугольника «на лету», когда я представляю их как GL_POINTS, но я не вижу производительности, которую я бы хотел увидеть. Я получаю, возможно, 20-50 кадров в секунду с 100 000 лезвий травы, и у меня есть приличный графический процессор. Мне интересно, не подходит ли мой подход, или если я достиг ограничений в моем GPU или если я делаю что-то неправильно или, может быть, если они быстрее (моя цель - отдельные клинки, где я могу идеально управлять вершинами) , Текстуры Я использую 256x256OpenGL Grass rendering

шагов рендеринга являются:

Создание ВАО и 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); 

затем My Vertex Shader:

#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 и все еще не проблема. My Geometry Shader:

#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; 

} 
+0

Я не могу сказать, но я думаю, что, возможно, быстрее пойти с приближением к плоскости. –

+0

О да, это определенно быстрее, если я пропущу этап геометрии и займусь простым спрайтом, но у меня нет возможности оживить вершины и создать реалистичное движение травы. –

+0

Нет, не точечные спрайты, я сказал, что это не точечный спрайт. Используйте instancing с плоскостями как сетка. –

ответ

3

Что вы хотите, это техника под названием Instancing. Учебник, который я связал, фантастичен для выяснения того, как делать инстанцирование.

Я бы предположил, что вы избегаете геометрического шейдера (поскольку геометрический шейдер обычно не хорошо масштабируется, когда его цель заключается в расширении количества вершин), а вместо этого просто определяют буфер, содержащий все вершины, необходимые для рисования один клинок (или патч) травы, затем используйте instancing, чтобы перерисовать этот объект тысячи раз.