【问题标题】:Creating rain drops创造雨滴
【发布时间】:2019-05-17 18:22:13
【问题描述】:
#include <stdio.h>  // this library is for standard input and output
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit

#define RAINSIZE 50
int winWidth = 1000, winHeight = 1000;
int counter = 0;
time_t t;
float rotationAngle = 0;

struct drop {
    float x = 400;
    float y = 400;
    float inc = 0.01;
    float radius = 5;
    float scale = 1.0;
    float rotationAngle = 0;
    float rotationInc = 1;
};

drop rain[RAINSIZE];

void initRain() {
    srand((unsigned)time(&t));
    for (int i = 0; i < RAINSIZE; i++) {
        rain[i].x = rand() % winWidth;
        rain[i].y = rand() % winHeight;
        rain[i].inc = 1.5 + (float)(rand() % 100) / 1000.0;
        rain[i].radius = (float)(rand() % 8);
        rain[i].scale = (float)(rand() % 20000) / 1000.0;
        rain[i].rotationAngle = (float)(rand() % 3000) / 1000.0;
        rain[i].rotationInc = (float)(rand() % 100) / 1000.0;
        if ((rand() % 100) > 50) {
            rain[i].rotationInc = -rain[i].rotationInc;
        }
    }
}

void drawParticleShape(int i) {
    glBegin(GL_POINTS);
    glVertex2d(rain[i].x, rain[i].y);
    glEnd();
    glBegin(GL_LINES);
    glVertex2d(rain[i].x, rain[i].y);
    glVertex2d(rain[i].x, rain[i].y + rain[i].radius * 2);
    glEnd();
}

void drawDrop(int i) {
    glColor3f(0.0, 0.0, 1.0);
    glLineWidth(2);
    drawParticleShape(i);
    rain[i].y -= rain[i].inc;
    if (rain[i].y < 0) {
        rain[i].y = winHeight;
    }
}

void drawRain() {
    for (int i = 0; i < RAINSIZE; i++) {
        drawDrop(i);
    }
}

// this is the initialisation function, called once only
void init() {
    glClearColor(0.0, 0.0, 0.0, 0.0); // set what colour you want the background to be
    glMatrixMode(GL_PROJECTION); // set the matrix mode, we will look at this later
    gluOrtho2D(0.0, winWidth, 0.0, winHeight);
}

float elapsedTime = 0, base_time = 0, fps = 0, frames;

void calcFPS() {
    elapsedTime = glutGet(GLUT_ELAPSED_TIME);
    if ((elapsedTime - base_time) > 1000.0) {
        fps = frames * 1000.0 / (elapsedTime - base_time);
        printf("fps: %f", fps);
        base_time = elapsedTime;
        frames = 0;
    }
    frames++;
}

// This is the display function it is called when ever you want to draw something
// all drawing should be called form here
void display() {
   glClear(GL_COLOR_BUFFER_BIT);
   drawRain();
   calcFPS();
   glFlush();
   counter++;
   glutPostRedisplay();
}

// This is the idle function it is called whenever the program is idle
// This has the effect of repeatedly calling the display function
void idle() {
    //display();
}

// As with many programming languages the main() function
// is the entry point for execution of the program
int main(int argc, char** argv) {
    srand(1);
    initRain();
    glutInit(&argc, argv);  //perform the GLUT initialization
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); // more initialisation
    glutInitWindowSize(winWidth, winHeight); // set window position
    glutInitWindowPosition(0, 0); // set window size
    glutCreateWindow("Hello"); // create a display with a given caption for the title bar
    glEnable(GL_BLEND); //Enable blending.
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set blending function.
    init(); // call init function defined above
    glutIdleFunc(idle); //  define what function to call when the program is idle
    glutDisplayFunc(display); // define what function to call to draw
    // the last function in the program puts the program into infinite loop
    glutMainLoop();
    // this line exits the program
    return 0;
}

我正在尝试创建从屏幕顶部落下并散开的雨滴,但雨滴无法正常下落。它应该像真正的雨一样落下。我试图弄清楚问题是什么,但我一直在让它变得更糟。如果您能帮助我并告诉我问题所在,我将不胜感激。

它是如何工作的:

我希望它如何工作(上图编辑):

【问题讨论】:

  • 您能否添加一个屏幕截图或更好地描述它当前的外观以及您想要什么?
  • 顺便说一句,我建议使用乘法而不是除法。在大多数情况下,乘法要快得多。也宁愿使用 static_cast 而不是 C-Style-Cast (float)
  • 我已编辑代码以显示为使雨看起来更逼真所做的更改。

标签: c++ visual-studio opengl


【解决方案1】:

您必须在每帧的开头通过glClear 清除默认帧缓冲区(“窗口”)的颜色平面。请注意,只要您不明确更改帧缓冲区的内容,它就不会更改。您绘制的所有内容都会保留,直到它被清除或覆盖。

进一步不要重绘idle中的窗口,而是通过glutPostRedisplay将当前窗口标记为需要在display中重新显示。 GLUT 事件处理循环将为您调用display

void display() {
    glClear( GL_COLOR_BUFFER_BIT );
    drawRain();
    calcFPS();
    glFlush();
    counter++;
    glutPostRedisplay();
}

void idle() {
    //display();
}

【讨论】:

  • 如何提高下雨的速度?我试图更改void calcFPS() 上的值,但它没有做任何事情。
  • @Muddy 速度取决于rain[i].inc。这是在rain[i].inc = 0.05 + (float)(rand() % 100) / 1000.0; 中计算的,增加因子,例如rain[i].inc = 0.2 + (float)(rand() % 100) / 1000.0;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
相关资源
最近更新 更多