123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- #include <GL/glew.h>
- #include <GLFW/glfw3.h>
- #include <math.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define WIDTH 800
- #define HEIGHT 800
- static const GLchar* vertexShaderCode = "#version 430\n"
- "layout(location = 0) in vec2 pos;"
- ""
- "out vec2 varTex;"
- ""
- "void main(void) {"
- " varTex = (pos + 1.0) * 0.5;"
- " gl_Position = vec4(pos, 0.0, 1.0);"
- "}";
- static const GLchar* fragmentShaderCode =
- "#version 430\n"
- ""
- "layout(binding = 0) uniform sampler2D samp;"
- ""
- "const vec4 heightColors[5] = {"
- " vec4(0.0, 0.0, 0.7, 1.0),"
- " vec4(0.0, 0.0, 1.0, 1.0),"
- " vec4(0.0, 1.0, 0.0, 1.0),"
- " vec4(0.6, 0.3, 0.0, 1.0),"
- " vec4(0.3, 0.3, 0.3, 1.0),"
- "};"
- ""
- "in vec2 varTex;"
- ""
- "out vec4 color;"
- ""
- "void main(void) {"
- " float f = texture(samp, varTex).r;"
- " color = vec4(f, f, f, 1.0);\n"
- " //color = heightColors[min(int(5 * f), 4)];\n"
- " //int a = int(min(floor(5 * f), 4));"
- " //int b = int(min(ceil(5 * f), 4));"
- " //color = mix(heightColors[a], heightColors[b], 5 * f - a);\n"
- "}";
- static GLFWwindow* window = NULL;
- static GLuint vertexShader = 0;
- static GLuint fragmentShader = 0;
- static GLuint program = 0;
- static GLuint vertexArray = 0;
- static GLuint vertexBuffer = 0;
- static GLuint texture = 0;
- static GLfloat noise[WIDTH][HEIGHT];
- static unsigned int seed = 1;
- static float nextSeededFloat(unsigned int x, unsigned int y) {
- unsigned int s = y + ((x + y) * (x + y + 1)) / 2;
- s ^= s * (x + seed) * 534492383u;
- s ^= s * (y + seed) * 23537u;
- return s / (float)(-1u);
- }
- static float interpolate(float a, float b, float f) {
- return (b - a) * (3.0 - f * 2.0) * f * f + a;
- }
- static float dot(int ix, int iy, float x, float y, float zoom) {
- float f =
- nextSeededFloat(ix % (int)(WIDTH / zoom), iy % (int)(HEIGHT / zoom)) *
- M_PI * 2.0f;
- return (x - ix) * cosf(f) + (y - iy) * sinf(f);
- }
- float perlin(float x, float y, float zoom) {
- x /= zoom;
- y /= zoom;
- int ix = x;
- int iy = y;
- int ix1 = ix + 1;
- int iy1 = iy + 1;
- float sx = x - ix;
- return interpolate(
- interpolate(dot(ix, iy, x, y, zoom), dot(ix1, iy, x, y, zoom), sx),
- interpolate(dot(ix, iy1, x, y, zoom), dot(ix1, iy1, x, y, zoom), sx),
- y - iy);
- }
- float transform(float x, float y, float zoom) {
- return (perlin(x, y, zoom) + 1.0f) * 0.5f;
- }
- float turbulence(int x, int y) {
- float sum = transform(x, y, 80.0f);
- sum += transform(x, y, 200.0f);
- sum += transform(x, y, 400.0f);
- return sum / 3.0f;
- }
- static void normalize() {
- float min = noise[0][0];
- float max = noise[0][0];
- for(int x = 0; x < WIDTH; x++) {
- for(int y = 0; y < HEIGHT; y++) {
- min = (min < noise[x][y] ? min : noise[x][y]);
- max = (max > noise[x][y] ? max : noise[x][y]);
- }
- }
- float divider = 1.0f / (max - min);
- for(int x = 0; x < WIDTH; x++) {
- for(int y = 0; y < HEIGHT; y++) {
- noise[x][y] = (noise[x][y] - min) * divider;
- }
- }
- }
- static void generateNoise() {
- for(int x = 0; x < WIDTH; x++) {
- for(int y = 0; y < HEIGHT; y++) {
- noise[x][y] = turbulence(x, y);
- }
- }
- normalize();
- (void)normalize;
- }
- static bool checkShaderError(GLuint shader, const char* name) {
- GLint status;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if(!status) {
- printf("cannot compile %s shader:\n", name);
- GLchar error[256];
- glGetShaderInfoLog(shader, 256, NULL, error);
- puts(error);
- return true;
- }
- return false;
- }
- static bool initShaders() {
- vertexShader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vertexShader, 1, &vertexShaderCode, NULL);
- glCompileShader(vertexShader);
- if(checkShaderError(vertexShader, "vertex")) {
- return true;
- }
- fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fragmentShader, 1, &fragmentShaderCode, NULL);
- glCompileShader(fragmentShader);
- if(checkShaderError(fragmentShader, "fragment")) {
- return true;
- }
- program = glCreateProgram();
- glAttachShader(program, vertexShader);
- glAttachShader(program, fragmentShader);
- glLinkProgram(program);
- GLint linked;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- if(!linked) {
- puts("cannot link program:");
- GLchar error[256];
- glGetProgramInfoLog(program, 256, NULL, error);
- puts(error);
- return true;
- }
- glUseProgram(program);
- return false;
- }
- static void initVertexBuffer() {
- glGenVertexArrays(1, &vertexArray);
- glBindVertexArray(vertexArray);
- glGenBuffers(1, &vertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
- glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(GLfloat) * 2, NULL);
- glEnableVertexAttribArray(0);
- GLfloat data[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
- 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f};
- glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
- }
- static void initTexture() {
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- generateNoise();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, HEIGHT, WIDTH, 0, GL_RED, GL_FLOAT,
- noise);
- }
- static bool init() {
- if(glewInit() != GLEW_OK) {
- puts("cannot init glew");
- return true;
- }
- if(initShaders()) {
- return true;
- }
- initVertexBuffer();
- initTexture();
- return false;
- }
- static bool createWindow() {
- glfwWindowHint(GLFW_RESIZABLE, false);
- window = glfwCreateWindow(WIDTH, HEIGHT, "Noise", NULL, NULL);
- if(window == NULL) {
- puts("cannot create window");
- return true;
- }
- glfwMakeContextCurrent(window);
- return false;
- }
- static void cleanUp() {
- glDeleteBuffers(1, &vertexBuffer);
- glDeleteVertexArrays(1, &vertexArray);
- glDeleteTextures(1, &texture);
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- glDeleteProgram(program);
- if(window != NULL) {
- glfwDestroyWindow(window);
- }
- glfwTerminate();
- }
- static void start() {
- if(createWindow() || init()) {
- return;
- }
- int i = 0;
- while(!glfwWindowShouldClose(window)) {
- glClear(GL_COLOR_BUFFER_BIT);
- glBindTexture(GL_TEXTURE_2D, texture);
- if(i++ == 100) {
- seed++;
- i = 0;
- generateNoise();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, HEIGHT, WIDTH, 0, GL_RED,
- GL_FLOAT, noise);
- }
- glActiveTexture(GL_TEXTURE0);
- glBindVertexArray(vertexArray);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
- }
- int main() {
- if(!glfwInit()) {
- puts("glfw init error");
- return 0;
- }
- start();
- cleanUp();
- return 0;
- }
|