gpt4 book ai didi

控制放大 Mandelbrot 集的位置

转载 作者:太空宇宙 更新时间:2023-11-03 23:23:53 25 4
gpt4 key购买 nike

我编写了一个简单的片段着色器来渲染 mandelbrot 集。我正在使用 c 语言和使用 glsl 的 opengl 执行此操作。

#version 330 core
in vec2 fCoord; //position.x position.y which is -1 to 1 on both axis
uniform int maxIterations;
uniform sampler1D mandiTexture;

out vec4 color;

void main()
{
vec2 c, z;

c.x = fCoord.x;
c.y = fCoord.y;

int i;
z = vec2(0.0f, 0.0f);
for(i=0; i<maxIterations; i++) {
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;

if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}

vec4 tcolor;

if (i == maxIterations)
{
tcolor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
else
{
tcolor = texture(mandiTexture, float(i) / float(maxIterations));
}
color = tcolor;
}

我注意到在调整初始 z 值时我得到了一些不同的结果,但大多数结果都超出了我的四边形。当 z 为 0, 0 时,我得到了这个结果。 enter image description here

如您所见,该组的左侧未在四边形上呈现。

c 值来自顶点着色器,所以我假设它在 x 轴和 y 轴上都为 -1 到 1,并在两者之间进行插值。

我的问题是:

  • 1) 如何让图片在四边形上居中?我不太确定
  • 2) 我怎么能说 zoom in on some in on the mandelbrot set and a跟进,假设我想放大场景的特定部分?
  • 2B) 假设我点击屏幕并获取 NDC 中的位置?
  • 3) 如果我将我的最大迭代次数设置得更高,这个集合似乎真的变得锯齿状,这是正常现象吗?

我想如果我能理解如何放大场景,我就能弄清楚如何放大特定部分,但我不确定。

编辑,确保我的代码是

主.c

int maxIterations = 70;
int iterAmount = 1;

char* vshad, *fshad;

GLuint verticesBuffer, colorBuffer, vao, texCoordBuffer, indicesBuffer;
GLuint mandiTextureID, sp;

mat4_s vm, pm, opm, tm;
GLint viewMat = -1;
GLint projMat = -1;
GLint modelMat = -1;

GLint mandiTexture = -1;
GLint maxIterLoc = -1;



void initShaders(void)
{

char* vertexShaderSource = getResource("vert.shad");
char* fragmentShaderSource = getResource("frag.shad");

vshad = readFile(vertexShaderSource);
fshad = readFile(fragmentShaderSource);

free(vertexShaderSource);
free(fragmentShaderSource);
}

int run_game()
{
current_utc_time(&start_time);
while(game_running)
{
current_utc_time(&current_time);
double frameTime = (diff(start_time,current_time).tv_sec + diff(start_time,current_time).tv_nsec) * .00000001;
//printf("float time: %0.8f\n",frameTime);
if ( frameTime > 0.25 )
{
frameTime = 0.25;
}
current_utc_time(&start_time);
current_time = start_time;

accumulator += frameTime;

while ( accumulator >= dt )
{
accumulator -= dt;
t += dt;
//printf("fixed update dt: %0.8f\n",dt);
}
//render_state = currentState * alpha + previousState * ( 1.0 - alpha );
const double alpha = accumulator / dt;
render();

if(game_running < 1) { break; }
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
game_running = -1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
game_running = -1;
break;
}
break;
}
}
}
return -1;
}

int main(int argc, char const *argv[]) {
initShaders();

mat4_identity(&vm);
vec3_s eye = {0, 0, 0};
vec3_s center = {0, 0, -1};
vec3_s up = {0, 1, 0};

mat4_lookAt(&vm, &eye, &center, &up);

mat4_identity(&opm);
mat4_ortho(&opm, 0, 200, 0, 200, 1, 100);

mat4_identity(&tm);
mat4_scalex(&tm, &tm, 100, 100, 0);
mat4_translatex(&tm, &tm, 100.0f, 100.0f, -20);

SDL_Surface* mandiSurface = loadPNG(getResource("mandi.png"));

if(!mandiSurface) {
printf("IMG_Load: %s\n", IMG_GetError());
// handle error
}

GLenum Mode1 = GL_RGB;

if(4 == mandiSurface->format->BytesPerPixel)
{
Mode1 = GL_RGBA;
printf("mode change");
}

sp = getShaderProgram(vshad, fshad);
r = newRenderable2d();

glGenVertexArrays(1, &vao);
glGenBuffers(1, &verticesBuffer);
glGenBuffers(1, &colorBuffer);
glGenBuffers(1, &indicesBuffer);
glGenBuffers(1, &texCoordBuffer);

glBindVertexArray(vao); //bind vertex array buffer

glBindBuffer(GL_ARRAY_BUFFER, verticesBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->vertices), r->vertices, GL_STATIC_DRAW);

//bind n setup indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(r->indices), r->indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind indices

//bind n setup colors
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->colors), r->colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind colors

//bind n setup texture coords
glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->texCoords), r->texCoords, GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind texture coords

glBindVertexArray(0); //unbind vertex array buffer

//mandi 1d texture
glGenTextures(1, &mandiTextureID);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);

glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexImage1D(GL_TEXTURE_1D, 0, Mode1, mandiSurface->w, 0, Mode1, GL_UNSIGNED_BYTE, mandiSurface->pixels);
glBindTexture(GL_TEXTURE_1D, 0);
free(mandiSurface);


while(run_game() >= 0);
free(r);
IMG_Quit();
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(window);
return 0;
}

void render()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glUseProgram(sp);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);//mandiTexture
mandiTexture = getUniformLocation(sp, "mandiTexture");
glUniform1i(mandiTexture, 0);


glBindVertexArray(verticesBuffer);
viewMat = getUniformLocation(sp, "viewMat");
modelMat = getUniformLocation(sp, "modelMat");
projMat = getUniformLocation(sp, "projMat");

maxIterLoc = getUniformLocation(sp, "maxIterations");

glUniformMatrix4fv(viewMat, 1, GL_FALSE, vm.m);
glUniformMatrix4fv(projMat, 1, GL_FALSE, opm.m);
glUniformMatrix4fv(modelMat, 1, GL_FALSE, tm.m);

glUniform1i(maxIterLoc, maxIterations);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

SDL_GL_SwapWindow(window);
}

int init_sdl(int width, int height, char* title, double fps)
{

if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
SDL_Log("sdl failed to init");
SDL_Quit();
return -1;
}

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);


window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(window == NULL)
{
SDL_Log("sdl failed to create window");
SDL_Quit();
return -1;
}

maincontext = SDL_GL_CreateContext(window);
if(maincontext == NULL)
{
SDL_Log("sdl failed to create opengl context");
SDL_Quit();
return -1;
}
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
SDL_GL_SetSwapInterval(1);


return 1;
}

顶点着色器

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 icolor;
layout (location = 2) in vec2 vTexCoord;

uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;

out vec4 fcolor;
out vec2 fTexCoord;
out vec2 fCoord;

void main()
{
gl_Position = projMat * viewMat * modelMat * vec4(position, 1.0);

fCoord = vec2(position);
fTexCoord = vTexCoord;
fcolor = vec4(icolor, 1.0f);
}

感谢@samgak,我能够解决我遇到的问题,现在我添加了一些 Mandelbrot 集的镜头。

enter image description here

enter image description here

enter image description here

最佳答案

The c value is coming from the vertex shader so i assume it goes for -1 to 1 on both x and y axis and being interpolated in between.

没错。

1) How can I center the image on the quad? I am not really sure of that.

您只需要缩小 1.5 倍并将其居中于 -0.5。 Mandelbrot 集的有趣部分在实轴上大致从 -2 延伸到 1,在虚轴上大致从 -i 延伸到 i:

enter image description here

2) How can I say zoom in on some in on the mandelbrot set and a follow up, lets say I want to zoom in on a specific part of the set? 2B) Let's say I click the screen and get the position in NDC?

放回之前版本中的 2 件制服:

uniform vec2 center;
uniform float scale;

声明变量以在您的 C 代码中保存这些值,并使用 glUniform2fglUniform1f 设置它们。要使集合居中,初始值应为 -0.5,中心为 0.0,比例为 1.5(较大的值缩小)。然后在你的片段着色器中,像这样应用它们:

c = (fCoord * scale) + center;

要单击屏幕并放大特定位置,请根据其在屏幕上的位置将鼠标位置转换为介于 -1、-1 和 1,1 之间的值,然后将上述等式应用于它以找到该位置你点击了。将其设置为新的中心并将比例乘以小于 1 的值以放大给定的量。

3) If I set my max iterations higher the set seems to get really jaggy, is that normal behavior?

您发布的屏幕截图看起来不错。如果您在片段着色器中实现某种多重采样可能看起来会更好(例如,在循环中计算多个值并将它们加在一起,以便每个像素实际上是 2x2 或 4x4 像素 block 的平均值等)。

如果您放大得足够远,最终您将遇到 GPU 使用的 float 精度的限制。

关于控制放大 Mandelbrot 集的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31926404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com