如何获得emscripten+ webGL呈现终止或所请求的输入

发布于 2025-01-25 19:07:03 字数 5284 浏览 5 评论 0 原文

我正在尝试使用Emscripten编写一些旧的C ++代码,以汇编为WebAssembly和WebGL。我有一个非常简单的单文件C ++项目,该项目呈现Mandelbrot集,该集合使用G ++效果很好。我运行它,实际上它确实使Mandelbrot构建了越来越多的细节。

我已经获得了使用EMCC编译的代码,这需要大量阅读...但是它仍然无法按照我的意愿工作。由于某种原因,当我进入HTML页面时,直到代码终止或要求输入之前,什么都没有呈现。当时,正确的帧(Mandelbrot集)实际上是

显然,我想要的是在帧速率计时器启动之前渲染的每个帧。但是,即使使用 glfinish()调用,我也无法正常工作。

有人会看我的代码,看看我是否做错了什么?

谢谢:

// Charles Swanson, [email protected]
// Written 2019/11/30
// Compile using:
// g++ SmallestOpenGL.cpp -o SmallestOpenGL_Bin -lGL -lglfw
// emcc SmallestOpenGL.cpp -o ../IgnoreMe/SmallestOpenGL.html -s USE_GLFW=3 -s MIN_WEBGL_VERSION=2

// Copyright me, all rights reserved for now.

#define GLFW_INCLUDE_ES3
#include <GLFW/glfw3.h>
#include <iostream>
#include <time.h>
#include <thread>

const char* vertexShaderSource = "#version 300 es\n"
    "layout (location = 0) in vec3 aPos;\n"
    "out float u;\n"
    "out float v;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "   u = aPos.x;\n"
    "   v = aPos.y;\n"
    "}\0";

const char* fragmentShaderSource = "#version 300 es\n"
    "precision mediump float;\n"
    "uniform float maxiters;\n"
    "in float u;\n"
    "in float v;\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
    "   float scaledx = (u-0.5)*1.5f;\n"
    "   float scaledy = v*1.0f;\n"
    "   float currentx = scaledx;\n"
    "   float currenty = scaledy;\n"
    "   float currentx2 = 0.0f;\n"
    "   float currenty2 = 0.0f;\n"
    "   for (int loopind = 1;loopind<int(maxiters);loopind++)\n"
    "   {\n"
    "      currentx2 = scaledx + currentx*currentx - currenty*currenty;\n"
    "      currenty2 = scaledy + 2.0f*currentx*currenty;\n"
    "      currentx = clamp(currentx2,-10000.0f,10000.0f);\n"
    "      currenty = clamp(currenty2,-10000.0f,10000.0f);\n"
    "   }\n"
    "   float amplitude = currentx2*currentx + currenty2*currenty;\n"
    "   if (amplitude>4.0)\n"
    "       FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
    "}\0";

int main(void)
{
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,0);

    GLFWwindow* window = glfwCreateWindow(400,300,"The Window Title",NULL,NULL);
    glfwMakeContextCurrent(window);

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
    glCompileShader(vertexShader);

    GLchar infoLog[256];
    glGetShaderInfoLog(vertexShader,256,NULL,infoLog);
    std::cout<<"Vertex shader info log says: "<<infoLog<<std::endl;

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader);

    glGetShaderInfoLog(fragmentShader,256,NULL,infoLog);
    std::cout<<"Fragment shader info log says: "<<infoLog<<std::endl;

    GLuint program = glCreateProgram();
    glAttachShader(program,vertexShader);
    glAttachShader(program,fragmentShader);
    glLinkProgram(program);

    glGetProgramInfoLog(program,256,NULL,infoLog);
    std::cout<<"Progam info log says: "<<infoLog<<std::endl;
    
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    float vertices[] = {
        -1.0f, -1.0f, 0.0f, // bottom left
        -1.0f,  1.0f, 0.0f, // top left 
         1.0f, -1.0f, 0.0f, // bottom right  
        -1.0f,  1.0f, 0.0f, // top left
         1.0f, -1.0f, 0.0f, // bottom right 
         1.0f, 1.0f, 0.0f, // top right 
    }; 

    GLuint VAO;
    glGenVertexArrays(1,&VAO);
    glBindVertexArray(VAO);
    glEnableVertexAttribArray(0);

    GLuint VBO;
    glGenBuffers(1,&VBO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_TRUE,3*sizeof(float),0);

    glUseProgram(program);

    GLuint maxitersLocation = glGetUniformLocation(program,"maxiters");
    GLuint xsizeLocation = glGetUniformLocation(program,"xsize");
    GLuint ysizeLocation = glGetUniformLocation(program,"ysize");
    std::cout<<"Maxiters location is "<<maxitersLocation<<std::endl;

    int xsize;
    int ysize;
    glfwGetWindowSize(window,&xsize,&ysize);
    std::cout<<"Window size is "<<xsize<<" x "<<ysize<<std::endl;

    glUniform1f(maxitersLocation,10);
    

    float iters = 0;
    while (iters<10)
    {
        
        iters = iters+0.1;
        if (iters>10)
                iters = 10;
        glUniform1f(maxitersLocation,iters);
        glClearColor(1,0.5,0,1);
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES,0,6);

        glfwSwapBuffers(window);
        glfwPollEvents();
        glFinish();
        std::this_thread::sleep_for(std::chrono::milliseconds(long(30)));
        
    }

    char in;
    std::cin>>in;
    glfwTerminate();
}

I'm trying to get some old C++ code I wrote to compile to WebAssembly and WebGL using Emscripten. I have a very simple one-file C++ project that renders the Mandelbrot set, which works great using g++. I run it and it does in fact render the Mandelbrot set in ever-increasing detail.

I've gotten my code to compile using emcc, which took a lot of reading... but it still doesn't work as I want. For some reason, when I go to the HTML page, nothing is rendered until the code either terminates or asks for input. At that time, the correct frame (the Mandelbrot set) is in fact rendered.

Obviously what I'd want is for each frame to render before the frame rate timer starts. However I can't get that to work, even with a glFinish() call.

Would someone please take a look at my code and see if I've done anything obvious wrong?

Thanks:

// Charles Swanson, [email protected]
// Written 2019/11/30
// Compile using:
// g++ SmallestOpenGL.cpp -o SmallestOpenGL_Bin -lGL -lglfw
// emcc SmallestOpenGL.cpp -o ../IgnoreMe/SmallestOpenGL.html -s USE_GLFW=3 -s MIN_WEBGL_VERSION=2

// Copyright me, all rights reserved for now.

#define GLFW_INCLUDE_ES3
#include <GLFW/glfw3.h>
#include <iostream>
#include <time.h>
#include <thread>

const char* vertexShaderSource = "#version 300 es\n"
    "layout (location = 0) in vec3 aPos;\n"
    "out float u;\n"
    "out float v;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "   u = aPos.x;\n"
    "   v = aPos.y;\n"
    "}\0";

const char* fragmentShaderSource = "#version 300 es\n"
    "precision mediump float;\n"
    "uniform float maxiters;\n"
    "in float u;\n"
    "in float v;\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
    "   float scaledx = (u-0.5)*1.5f;\n"
    "   float scaledy = v*1.0f;\n"
    "   float currentx = scaledx;\n"
    "   float currenty = scaledy;\n"
    "   float currentx2 = 0.0f;\n"
    "   float currenty2 = 0.0f;\n"
    "   for (int loopind = 1;loopind<int(maxiters);loopind++)\n"
    "   {\n"
    "      currentx2 = scaledx + currentx*currentx - currenty*currenty;\n"
    "      currenty2 = scaledy + 2.0f*currentx*currenty;\n"
    "      currentx = clamp(currentx2,-10000.0f,10000.0f);\n"
    "      currenty = clamp(currenty2,-10000.0f,10000.0f);\n"
    "   }\n"
    "   float amplitude = currentx2*currentx + currenty2*currenty;\n"
    "   if (amplitude>4.0)\n"
    "       FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
    "}\0";

int main(void)
{
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,0);

    GLFWwindow* window = glfwCreateWindow(400,300,"The Window Title",NULL,NULL);
    glfwMakeContextCurrent(window);

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
    glCompileShader(vertexShader);

    GLchar infoLog[256];
    glGetShaderInfoLog(vertexShader,256,NULL,infoLog);
    std::cout<<"Vertex shader info log says: "<<infoLog<<std::endl;

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader);

    glGetShaderInfoLog(fragmentShader,256,NULL,infoLog);
    std::cout<<"Fragment shader info log says: "<<infoLog<<std::endl;

    GLuint program = glCreateProgram();
    glAttachShader(program,vertexShader);
    glAttachShader(program,fragmentShader);
    glLinkProgram(program);

    glGetProgramInfoLog(program,256,NULL,infoLog);
    std::cout<<"Progam info log says: "<<infoLog<<std::endl;
    
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    float vertices[] = {
        -1.0f, -1.0f, 0.0f, // bottom left
        -1.0f,  1.0f, 0.0f, // top left 
         1.0f, -1.0f, 0.0f, // bottom right  
        -1.0f,  1.0f, 0.0f, // top left
         1.0f, -1.0f, 0.0f, // bottom right 
         1.0f, 1.0f, 0.0f, // top right 
    }; 

    GLuint VAO;
    glGenVertexArrays(1,&VAO);
    glBindVertexArray(VAO);
    glEnableVertexAttribArray(0);

    GLuint VBO;
    glGenBuffers(1,&VBO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_TRUE,3*sizeof(float),0);

    glUseProgram(program);

    GLuint maxitersLocation = glGetUniformLocation(program,"maxiters");
    GLuint xsizeLocation = glGetUniformLocation(program,"xsize");
    GLuint ysizeLocation = glGetUniformLocation(program,"ysize");
    std::cout<<"Maxiters location is "<<maxitersLocation<<std::endl;

    int xsize;
    int ysize;
    glfwGetWindowSize(window,&xsize,&ysize);
    std::cout<<"Window size is "<<xsize<<" x "<<ysize<<std::endl;

    glUniform1f(maxitersLocation,10);
    

    float iters = 0;
    while (iters<10)
    {
        
        iters = iters+0.1;
        if (iters>10)
                iters = 10;
        glUniform1f(maxitersLocation,iters);
        glClearColor(1,0.5,0,1);
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES,0,6);

        glfwSwapBuffers(window);
        glfwPollEvents();
        glFinish();
        std::this_thread::sleep_for(std::chrono::milliseconds(long(30)));
        
    }

    char in;
    std::cin>>in;
    glfwTerminate();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜味超标? 2025-02-01 19:07:03

好的,我发现了。许多网络示例实现了解决方案;我想我掩盖了他们。这里有几个:

https://github.com/github.com/pcbaecker/pcbaecker/pcbaecker/example-example-example--emspample--emspample-webgl

https://github.com /qafool​​abs/emscripten-opengl-example“ rel =“ nofollow noreferrer”> https://github.com/qafool​​abs/emscripten-opengl-example

关键是使用在 emscripten.h.h.h.h.h.h.h.h.h 称为 emscripten_set_main_loop 。将该功能传递给您的渲染功能,并呈现每个帧。出色的!

Ok, I figured it out. Many web examples implement the solution; I guess I glossed over them. Here are a few:

https://github.com/pcbaecker/example-emscripten-webgl

https://gist.github.com/mortennobel/0e9e90c9bbc61cc99d5c3e9c038d8115

https://gist.github.com/ousttrue/0f3a11d5d28e365b129fe08f18f4e141

https://github.com/QafooLabs/emscripten-opengl-example

The key is to use the function implemented in Emscripten.h called emscripten_set_main_loop. Pass that function a handle to your render function, and it renders every frame. Excellent!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文