opengl:延迟照明奇怪的工件

pbpqsu0x  于 2021-07-05  发布在  Java
关注(0)|答案(0)|浏览(181)

在进行延迟照明时,会出现3个工件。
奇怪的带子[至少在我看来是这样]

如果你看一看带圆圈的圆柱体的顶部,你会看到它是如何扭曲地延伸,模糊了它后面的场景。我不知道发生了什么事
剥离线

如果你看圆柱体,你会看到一条奇怪的线,它会出现在所有的物体上,这取决于你看它的Angular 。
3.屏幕撕裂
只观察球体

现在,当我向下旋转相机,使球体移动到屏幕的顶部边缘时,它开始拉伸

因为我的程序是相当大的,我不知道哪里出了问题,我将张贴什么,我觉得是项目的相关部分在这里。如果需要更多的信息,请告诉我。
让我们从最重要的帧缓冲区开始

public class FrameBuffer
{
 private final int fboID;
 private final int Width;
 private final int Height;

 private final Texture2D colorBuffers[];
 private final RenderBuffer depthStencil;

 private RenderingAttributes render;

 public FrameBuffer(int width,int height)
 {
  Width=width;
  Height=height;

  fboID=GL30.glGenFramebuffers();
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER,fboID);
  {
   colorBuffers=new Texture2D[3];  // create 3 textures
   colorBuffers[0]=new Texture2D(GL30.GL_RGB32F,GL11.GL_RGB,GL11.GL_NEAREST,width,height,GL30.GL_COLOR_ATTACHMENT0); //used to store scene vertex positions in worldSpace
   colorBuffers[1]=new Texture2D(GL30.GL_RGB32F,GL11.GL_RGB,GL11.GL_NEAREST,width,height,GL30.GL_COLOR_ATTACHMENT1); //used to store scene normals in worldSpace
   colorBuffers[2]=new Texture2D(GL11.GL_RGB,GL11.GL_RGB,GL11.GL_LINEAR,width,height,GL30.GL_COLOR_ATTACHMENT2); //final output image blitted to screen

   depthStencil=new RenderBuffer(GL30.GL_DEPTH24_STENCIL8,width,height); //used in gBuffer pass for depth testing
  }
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER,0);
 }

 //Attach/Detach frameBuffer for each pass
 //RenderingAttributes is  a class used to set and unset glParameters like blending,depth testing 
 //etc based on what pass im rendering i will show the details in a minute
 public void bind(RenderingAttributes binding,boolean enable) 
 {
  if(enable)
  {
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER,fboID);
   GL11.glViewport(0,0,Width,Height);
   if(binding!=null){(render=binding).setOps();}  //what operations to perform before rendering
  }
  else
  {
   GL11.glViewport(0,0,Display.getWidth(),Display.getHeight());
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER,0);
   if(render!=null){render.disableOps();}        //what operations to perform after rendering
  }
 }

 //Used by pointLight pass to read vertexPositions and normals from the gBuffer Textures
 public void attachTexture(int textureID,int textureBank)
 {
  Texture2D texture=colorBuffers[textureID];
  texture.bindTexture(textureBank);
 }

 //Used to resolve COLOR_ATTACHMENT_2[final output] to screen
 public void resolveToScreen(int attachment)
 {
   GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER,0);
   GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER,fboID);
   GL11.glDrawBuffer(GL11.GL_BACK);
   GL11.glReadBuffer(attachment);
   GL30.glBlitFramebuffer(0,0,Width,Height
                         ,0,0,Display.getWidth(),Display.getHeight()
                         ,GL11.GL_COLOR_BUFFER_BIT,GL11.GL_LINEAR);  
   GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER,0);
   GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER,0);   
 }

 //CalnUp
 public void release()
 {
  for(Texture2D tex:colorBuffers){tex.release();}
  depthStencil.release();
  GL30.glDeleteFramebuffers(fboID);
 }

 private static final class Texture2D
 {
  private final int textureID;

  private Texture2D(int textureFormat,int imageFormat,int filter,int width,int height,int attachment)
  {
   GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureID=GL11.glGenTextures());
   GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0
                    ,textureFormat,width,height,0
                    ,imageFormat,GL11.GL_FLOAT,(FloatBuffer)null);
   GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_MIN_FILTER,filter);
   GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_MAG_FILTER,filter);
   GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_S,GL11.GL_CLAMP);
   GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_T,GL11.GL_CLAMP);
   GL11.glBindTexture(GL11.GL_TEXTURE_2D,0);

   GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER,attachment,textureID,0);
  }

  private void bindTexture(int textureBank)
  {
   GL13.glActiveTexture(textureBank);
   GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureID);
  }
  private void release(){GL11.glDeleteTextures(textureID);}
 }

 //DepthBuffer used for gBuffer pass
 private static final class RenderBuffer
 {
  private final int bufferID;

  private RenderBuffer(int format,int width,int height)
  {
   GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER,bufferID=GL30.glGenRenderbuffers());
   GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER,format,width,height);
   GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER,GL30.GL_DEPTH_STENCIL_ATTACHMENT,GL30.GL_RENDERBUFFER,bufferID);
   GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER,0);
  }

  private void release(){GL30.glDeleteRenderbuffers(bufferID);}
 }
}

现在每个通道有3个主要组件
渲染属性:-在附加和分离帧缓冲区以进行渲染时执行的操作集
着色器
写入帧缓冲区的实际渲染器
1) g缓冲通行证
下面是我的gbuffer过程的渲染属性

private static final class Rendering implements RenderingAttributes
 {
  private final IntBuffer colorTargets;

  private Rendering()
  {
   colorTargets=BufferUtils.createIntBuffer(3);
   colorTargets.put(GL30.GL_COLOR_ATTACHMENT0).put(GL30.GL_COLOR_ATTACHMENT1).put(GL30.GL_COLOR_ATTACHMENT2);
   colorTargets.flip();
  }

  @Override
  public void setOps()
  {
   GL11.glEnable(GL11.GL_CULL_FACE);  //cull backside of all geometry we don't need those vertices in the gBuffer
   GL11.glCullFace(GL11.GL_BACK);

   GL20.glDrawBuffers(colorTargets);    //enable all 3 colorTargets, we won't draw to the last one we only clear it
   GL11.glEnable(GL11.GL_DEPTH_TEST);   //enable depth test for proper results
   GL11.glDepthMask(true);              //allow writing to depth buffer

   GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); //clear current color and depth of all attachments
  }

  @Override
  public void disableOps()   //called when attach(null,false) is called on frameBuffer basically the exact opposite operations of setOps
  {
   GL11.glDisable(GL11.GL_CULL_FACE);  //disable culling
   GL20.glDrawBuffers(GL11.GL_NONE);   //don't draw to anything
   GL11.glDepthMask(false);            //don't write to depth Buffer
   GL11.glDisable(GL11.GL_DEPTH_TEST); //disable depth testing
  }
 }

这是我的gbuffer过程顶点和片段着色器

Vertex Shader

# version 430 core

uniform mat4 P,V,M;  //P Perspective , V view ,M model matrices

in vec3 vertex;
out vec3 vertexMap;

in vec3 normal;
out vec3 normalMap;

void main()
{
 vec4 worldVertex=M*vec4(vertex,1.0);
 gl_Position=P*V*worldVertex;

 vertexMap=worldVertex.xyz;                              //output vertexPosition in worldSpace
 normalMap=normalize(vec3((M*vec4(normal,0.0)).xyz));    //output normal in worldSpace
}

My fragment shader

# version 430 core

in vec3 vertexMap;
in vec3 normalMap;

layout(location=0) out vec4 vertexBuffer;  //output to color_attachment_0
layout(location=1) out vec4 normalBuffer;  //output to color_attachment_1

void main()
{
 vertexBuffer=vec4(vertexMap,0);
 normalBuffer=vec4(normalMap,0);
}

最后我把这个交给我的朋友

public void render(Camera cam)
{
  fbo.bind(gRenderer,true);                //begin
  sceneRenderer.renderGlobal(cam,gShader); //gives every entity my gBuffer shader for rendering
  fbo.bind(null,false);                    //end
}

下面是包含vertexpositions的彩色附件0的外观

下面是包含顶点法线的颜色附件1的外观

2) 点光通
从这篇文章我读到它有两个子过程
a) 模板传递
这是我的模具渲染属性

private static final class StencilRendering implements RenderingAttributes
 {
  @Override
  public void setOps()
  {
   GL20.glDrawBuffers(GL11.GL_NONE);       //no draw buffers
   GL11.glDisable(GL11.GL_CULL_FACE);      //no cull face for reasons explained in the article
   GL11.glEnable(GL11.GL_DEPTH_TEST);      //enable depth test cause stencil test depends on it

   GL11.glEnable(GL11.GL_STENCIL_TEST);     //set the stencil ops
   GL11.glStencilMask(0xff);
   GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);

   GL11.glStencilFunc(GL11.GL_ALWAYS,0,0xFF); //as explained in the article
   GL20.glStencilOpSeparate(GL11.GL_FRONT,GL11.GL_KEEP,GL14.GL_DECR_WRAP,GL11.GL_KEEP); 
   GL20.glStencilOpSeparate(GL11.GL_BACK,GL11.GL_KEEP,GL14.GL_INCR_WRAP,GL11.GL_KEEP);
  }
  @Override
  public void disableOps()
  {
   GL11.glDisable(GL11.GL_DEPTH_TEST);   
   GL11.glDisable(GL11.GL_STENCIL_TEST);
  }
 }

这是我的模板着色器。这里什么都没发生

Vertex shader

   # version 430 core

   uniform mat4 P,V,M;
   in vec3 vertex;

   void main(){gl_Position=P*V*M*vec4(vertex,1.0);}

 Fragment shader

 # version 430 core

 out vec4 pixelColor;

 void main(){pixelColor=vec4(1,1,1,0f);}

b) 浅色通行证
以下是我的灯光渲染属性

private static final class ColorRendering implements RenderingAttributes
 {
  @Override
  public void setOps()
  {
   GL20.glDrawBuffers(GL30.GL_COLOR_ATTACHMENT2);  //draw to final output buffer

   GL11.glDisable(GL11.GL_DEPTH_TEST);            
   GL11.glEnable(GL11.GL_CULL_FACE);
   GL11.glCullFace(GL11.GL_FRONT);

   GL11.glEnable(GL11.GL_BLEND);                  //enable blending to add lightOutput for multiple lights
   GL11.glBlendFunc(GL11.GL_ONE,GL11.GL_ONE);
   GL14.glBlendEquation(GL14.GL_FUNC_ADD); 

   GL11.glEnable(GL11.GL_STENCIL_TEST);          //enable stencil test so only pixels within the lights bounding sphere gets rendered
   GL11.glStencilFunc(GL11.GL_EQUAL,1,0xFF);
  }
  @Override
  public void disableOps()
  {
   GL20.glDrawBuffers(GL11.GL_NONE);
   GL11.glDisable(GL11.GL_CULL_FACE);  
   GL11.glDisable(GL11.GL_BLEND);
   GL11.glDisable(GL11.GL_STENCIL_TEST);
   GL11.glEnable(GL11.GL_DEPTH_TEST);
  }
 }

这是我的着色器

Vertex Shader

 # version 430 core

uniform mat4 P,V,M;
in vec3 vertex;

void main(){gl_Position=P*V*M*vec4(vertex,1.0);}

Fragment Shader

# version 430 core

uniform sampler2D vertexBuffer;
uniform sampler2D normalBuffer;
uniform int ScreenWidth;
uniform int ScreenHeight;

uniform vec3 color;
uniform vec3 position;
uniform vec3 attenuation;

out vec4 pixelColor;

vec2 genTexCoord()
{
 vec2 texCoord=vec2(0.0);
 texCoord.x=gl_FragCoord.x/ScreenWidth;
 texCoord.y=gl_FragCoord.y/ScreenHeight;
 return texCoord;
}

float getAtten(float length)
{
 float intencity=0;
 intencity+=attenuation.x;
 intencity+=attenuation.y*(length);
 intencity+=attenuation.z*(length*length);
 return intencity;
}

void main()
{   
 vec3 finalColor=vec3(0);

 vec2 vertexTexCoord=genTexCoord();
 vec3 actualVertex=texture(vertexBuffer,vertexTexCoord).xyz;
 vec3 actualNormal=normalize(texture(normalBuffer,vertexTexCoord).xyz);

 vec3 lightDir=position-actualVertex;
 float atten=getAtten(length(lightDir));
 float maxIntencity=(max(dot(normalize(lightDir),actualNormal),0f));
 finalColor+=(color*maxIntencity)/atten;

 pixelColor=vec4(finalColor,0.0);
}

这里是我如何渲染我的点光通行证

public void render(Camera cam)
 {
  fbo.bind(null,true);             // i don't use the ops for my frameBuffer cause it has 2 passes

  for(PointLight pLight:lights)
  {
   light.translate(pLight.getPosition());  //light is an sphere entity having sphere geometry and modelMatrix for position and scale
   light.scale((float)pLight.getRadius());

   stencil.setOps();                        //Stencil Pass
   light.setShader(stencilShader);
   light.render(cam);
   stencil.disableOps();

   color.setOps();                          //Color pass
   light.setShader(colorShader);
   light.render(cam);
   color.disableOps();
  }

  fbo.bind(null,false);
 }

c) 最终管道

class PipeLine
{
 private final FrameBuffer fbo;

 private final GBufferPass pass1;
 private final PLightPass  pass2;

 PipeLine()throws IOException
 {
  fbo=new FrameBuffer(Display.getWidth(),Display.getHeight());

  pass1=new GBufferPass(fbo);
  pass2=new PLightPass(fbo);
 }

 void render(Camera cam)
 {
  pass1.render(cam);
  pass2.render(cam);

  fbo.resolveToScreen(GL30.GL_COLOR_ATTACHMENT2);  //output final image to screen
 }

 void cleanUp()
 {
  fbo.release();

  pass1.cleanUp();
  pass2.cleanUp();
 }
}

即使是一个猜测或可能性,为什么我得到上述人工制品将是很大的帮助。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题