在OpenGL中将四边形分层

Posted

技术标签:

【中文标题】在OpenGL中将四边形分层【英文标题】:Layering quads on top of each other in OpenGL 【发布时间】:2015-03-11 04:58:05 【问题描述】:

我正在使用 C++ 使用 OpenGL 创建一个基于 2D 瓷砖的战术 rpg,但我在分层瓷砖/四边形时遇到了困难。我希望能够说一个树纹理四边形,图像是树的周围透明 alpha 层,在不透明的草纹理四边形之上。我需要让树出现在草的顶部,草通过树图像的 alpha 层显示。

到目前为止,我一直在搞乱 glDisable(GL_DEPTH_TEST)、glEnable(GL_BLEND) 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 但到目前为止还没有运气。我最终得到了黑色背景上的一棵树,而不是草砖。有人能指出我正确的方向吗?

下面是我的渲染函数和初始化函数,它们可能是最相关的。

void View::initialize() 
  updateProjection(window);
  glDisable(GL_DEPTH_TEST);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  camera = new Camera(Vector3(-1, -3, 25), Vector3(-1, -3, 0), Vector3(0, 1, 0));
  loadImages();
  initShaders();

  //needed for transparency?
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


void View::render(World* worldTemp)

  Matrix4 mvpMatrix, viewMatrix, modelMatrix;
  Matrix4 XAxisRotationMatrix, YAxisRotationMatrix, ZAxisRotationMatrix;

  input->handleInput(camera, worldTemp->getPlayer());

  worldTemp->timerTick();
  worldTemp->clearFog();

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);            // Clear Screen and Depth Buffer

  XAxisRotationMatrix = Matrix4::IDENTITY;
  YAxisRotationMatrix = Matrix4::IDENTITY;
  ZAxisRotationMatrix = Matrix4::IDENTITY;
  XAxisRotationMatrix.rotate(Vector3(1.0, 0.0, 0.0), XAxisRotationAngle);
  YAxisRotationMatrix.rotate(Vector3(0.0, 1.0, 0.0), YAxisRotationAngle);
  ZAxisRotationMatrix.rotate(Vector3(0.0, 0.0, 1.0), ZAxisRotationAngle);

  viewMatrix = camera->getViewMatrix();

  modelMatrix = translationMatrix(Vector3(-4, 2, 0));
  mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;

  //Spit out the map
  for (int i = 0; i < 100; i++)
      for (int j = 0; j < 100; j++)
          for (int t = 0; t < 5; t++)
              if (worldTemp->getTile(i, j)->isOccupied() == true) 
                  if (worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getFog())
                    worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getEntityQuad()->render_self(mvpMatrix, true);
                  
                  else
                    worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getEntityQuad()->render_self(mvpMatrix);
                  
              
          
      
  

  //Place the player
  worldTemp->getPlayer()->getEntityQuad()->render_self(mvpMatrix);
  renderEnemies();

  glutSwapBuffers(); //works with GL_DOUBLE. use glFlush(); instead, if using GL_SINGLE

【问题讨论】:

你确定你的树纹理实际上有一个透明度正确的 alpha 分量吗?然后,必须最后渲染树。我在这里的回答详细解释了各种透明度渲染选项:***.com/a/23283256/3530129. 【参考方案1】:

基本上,在 2D 游戏中,分层是通过渲染调用的顺序完成的。如果你想让 A 层在 B 层之上,你应该先渲染 B 层,然后再渲染 A 层。

您使用的混合功能应取决于图像的纹理格式。 alpha 有两种常见的格式:

    预乘 alpha

    直接阿尔法

    更多信息:https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre

opengl es2 premultiplied vs straight alpha + blending

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);用于预乘 alpha,如果您按原样使用颜色,它应该可以很好地工作。 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);用于直接 alpha。

【讨论】:

以上是关于在OpenGL中将四边形分层的主要内容,如果未能解决你的问题,请参考以下文章

如何在OpenGL中将像素作为纹理绘制到多边形?

纹理中的 OpenGL 片段着色器

在 OpenGL 中将粒子渲染为具有透明度的 GL_TRIANGLE_FAN

在OpenGL中围绕坐标旋转四边形

OpenGL的镶嵌

OpenGL核心配置文件不会纹理四边形