簡體   English   中英

如何在OpenGL的立即模式下永久繪制內容?

[英]How to permanently draw things in OpenGL's Immediate mode?

我在創建路徑跟蹤器時遇到了一個小問題。

在我的項目中,我有一個對象,它通過while循環中完成的更新功能不斷地有機地移動。 我使用立即模式並將玩家表示為正方形,我想這樣做以便每次更新對象都是在當前位置繪制的,但也是為了繪制它的先前位置,所以蝕刻點朝向路徑對象正在進行中。 我很確定我們可以通過正常繪制位置來實現這一點,但是在while循環中的這個實例之后不會清除所有內容,但我不知道如何執行此操作。

編輯:對於那些想要代碼的人來說,要明白這段代碼特別是不符合這個問題而且我做了大量的概括(例如粒子被引用到一個對象)以便一般問題的要點是可以理解的:

#include "PerlinNoise.hpp"
#include "Particle.hpp"

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <vector>

using namespace siv;

float map(float oValue, float oMin, float oMax, float nMin, float nMax)
{
  float oRange = (oMax - oMin);
  float nRange = (nMax - nMin);
  return(((oValue - oMin) * nRange)/oRange) + nMin;
}

void drawRectangle(float x, float y, float xr, float yr, float R, float G, float B)
{
  glBegin(GL_QUADS);
  glColor3f(R,G,B);
  glVertex2f(x,y);
  glVertex2f(x+xr,y);
  glVertex2f(x+xr,y+yr);
  glVertex2f(x,y+yr);
  glEnd();
}

void drawLine(float x, float y, float xr, float yr, float rotation)
{
  float radius = sqrt(xr*xr + yr*yr);
  float a0 = asin(yr/radius);
  float tangle = a0+rotation;
  //std::cout<<tangle*180/M_PI<<std::endl;
  glBegin(GL_LINES);
  glColor3f(.1,.1,.1);
  glVertex2f(x,y);
  glVertex2f(x + sin(tangle)*radius,y + cos(tangle)*radius);
  glEnd();
}


int main()
{
  float inc = 0.1;
  int scl   = 20;
  int cols,rows;

  Particle particles[100000];

  //V2D flowfield[cols*rows];

  GLFWwindow* window;
  if (!glfwInit())
    return 1;
  int width  = 800;
  int height = 800;
  window = glfwCreateWindow(width, height, "Window", NULL, NULL);
  cols = floor(width/scl);
  rows = floor(height/scl);
  V2D flowfield[cols*rows];
  float zoff = 0;
  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);
  if(glewInit()!=GLEW_OK)
    std::cout<<"Error"<<std::endl;
  glEnable(GL_DEPTH_TEST);
  glMatrixMode(GL_PROJECTION);
  glfwGetFramebufferSize(window, &width, &height);
  glOrtho(0, width*(width/height), height, 0, -2, 2);
  PerlinNoise png = PerlinNoise(1);
  while(!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glClearColor(0.11, 0.14, 0.17, 1);
    float yoff = 0;
    for(int y = 0; y < rows; y++)
    {
      float xoff = 0;
      for(int x = 0; x < cols; x++)
      {
        double noise = map(png.noise((double)xoff, (double)yoff, (double)zoff),-1,1,0,1);
        double angle = noise * 8 *M_PI;
        //std::cout<<angle/(2*M_PI)<<std::endl;
        int index = x + y * cols;
        V2D v = V2D(cos(angle), sin(angle));
        v.normalize();
        v = V2D(v.x*5,v.y*5);
        flowfield[index] = v;
        //drawLine(x*scl, y*scl, scl, 0, atan2(v.x, v.y));
        //drawRectangle(x*scl,y*scl,scl,scl,noise,noise,noise);

        xoff += inc;
      }
      yoff += inc;
      zoff += 0.0001;
    }
    for(int i = 0; i < 100000; i++)
    {
      particles[i].follow(flowfield);
      particles[i].update();
      particles[i].show();
    }
    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  glfwTerminate();
}

當直接繪制到窗口時(無論是否雙重緩沖都沒有區別),您不得對其內容在繪圖之間持久進行任何假設。 哎呀,嚴格來說,在事情結束之前,內容可能會在畫中期受損; 當然,在實踐中這不太可能發生,並且鑒於現代合成圖形系統,它幾乎被淘汰了。

您的應用程序尖叫為繪制到中間幀緩沖對象。 無論發生什么事情,FBO都保證保留其內容; 您也可以隨時將其他繪圖添加到FBO的后備緩沖區中。

官方OpenGL wiki在https://www.khronos.org/opengl/wiki/Framebuffer_Object上描述了FBO

很久以前我寫了一個簡單的代碼示例(使用了大量過時的遺留OpenGL); 繪圖是遺留的,但FBO部分今天就像10年前一樣完成: https//github.com/datenwolf/codesamples/blob/master/samples/OpenGL/minimalfbo/minimalfbo.c (我使用render實現它紋理;渲染到渲染緩沖區和緩沖區blit到主幀緩沖區也適合你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM