我正在研究2d引擎.它已经工作得很好,但我不断得到像素错误.
例如,我的窗口是960x540像素,我从(0,0)到(959,0)画一条线.我希望扫描线0上的每个像素都会被设置为一种颜色,但是没有:最右边的像素没有被绘制.当我垂直绘制到像素539时,同样的问题.我真的需要绘制到(960,0)或(0,540)来绘制它.
由于我出生在像素时代,我确信这不是正确的结果.当我的屏幕大于320x200像素时,我可以从0到319以及从0到199进行绘制,我的屏幕将会满.现在我最终得到一个没有绘制右/底像素的屏幕.
这可能是由于不同的原因:我期望将opengl线基元从像素绘制到包含像素,最后一个像素实际上是独占的?是吗?我的投影矩阵不正确?我有一个错误的假设,当我有一个960x540的后备缓冲区时,实际上有一个像素更多?别的什么?
有人可以帮帮我吗?我一直在研究这个问题很长一段时间,每当我认为它没问题的时候,我看了一会儿它实际上没有.
这是我的一些代码,我试图尽可能地删除它.当我调用我的线函数时,每个坐标都加上0.375,0.375,以使它在ATI和nvidia适配器上都正确.
int width = resX();
int height = resY();
for (int i = 0; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(1, 0, 0, 1));
for (int i = 1; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(0, 1, 0, 1));
// when I do this, one pixel to the right remains undrawn
void rendermachine::line(int x1, int y1, int x2, int y2, const vec4f &color) …Run Code Online (Sandbox Code Playgroud) 在尝试将我的游戏引擎移植到mac时,我偶然发现了一个基本(但很大)的问题.在Windows上,我的主要代码看起来像这样(非常简化):
PeekMessage(...) // check for windows messages
switch (msg.message)
{
case WM_QUIT: ...;
case WM_LBUTTONDOWN: ...;
...
}
TranslateMessage(&msg);
DispatchMessage (&msg);
for (std::vector<CMyBackgroundThread*>::iterator it = mythreads.begin(); it != mythreads.end(); ++it)
{
(*it)->processEvents();
}
... do other useful stuff like look if the window has resized and other stuff...
drawFrame(); // draw a frame using opengl
SwapBuffers(hDC); // swap backbuffer/frontbuffer
if (g_sleep > 0) Sleep(g_sleep);
Run Code Online (Sandbox Code Playgroud)
我已经读过这不是mac方式.mac方式是检查某种事件,例如屏幕的v-sync以呈现新帧.但正如你所看到的,我想做的不仅仅是渲染,我希望其他线程能够工作.有些线程需要比每1/60秒更快地调用一次.(顺便说一句,我的线程基础结构是:线程将事件放入同步队列中,主线程调用processEvents来处理主线程内该同步队列中的项目.这用于网络内容,图像加载/处理内容,perlin噪声一代等...等...)
我希望能够以类似的方式做到这一点,但很少有关于此的信息.我不介意将渲染放在v-sync事件上(我也将在Windows上实现),但我希望对其余代码有更多响应.
以这种方式看待它:我很乐意能够处理其余部分,而GPU正在做任何事情,我不想等待v-sync然后开始做已经处理过的东西才开始将内容发送到GPU.你明白我的意思吗?
如果我需要从完全不同的角度来看待这个问题,请告诉我.
如果我需要阅读书籍/指南/教程/任何内容,请告诉我要阅读的内容!
我不是可可开发人员,我不是对象程序员,我的游戏引擎完全是用C++编写的,但我知道我的方式足以让xcode出现并显示我在该窗口内绘制的内容.它只是不像我的Windows版本更新,因为我不知道如何正确.
更新:我甚至认为我需要某种循环,即使我想在垂直回扫上同步.MacOSX文档中的OpenGL编程显示,这是通过设置SwapInterval来完成的.因此,如果我理解正确,在Mac上实时渲染时,我总是需要某种循环,使用swapInterval设置来降低功耗.这是真的?
我正在开发一款游戏引擎,它已经有了很大的发展.因为引擎也需要在mac上运行,我仍然使用OpenGL 3.2和GLSL 1.2 :-(.我使用GLEW,我认为它可以为我解决扩展问题.
编辑:同时,部分问题得到解答 - 请在下一次编辑时阅读:
我总是能够使着色器在windows和mac上工作,有时我必须在GLSL代码中添加一行,如#extension GL_EXT_gpu_shader4:enable使其在Mac上运行.看来我的Windows版本在编译同一个着色器时会发出警告,但它会起作用.
但自从我开始使用几何着色器以来,我的梦魇就开始了.出于某种原因,mac希望我使用#extension GL_EXT_gpu_shader4:enable而windows期望我使用#extension GL_EXT_geometry_shader4:enable.这使得创建独立于平台的着色器变得不那么明显.
而且,这更令人讨厌:Windows版本要我使用:glTransformFeedbackVaryings我认为GLEW会使它可用于mac但是我明确需要使用glTransformFeedbackVaryingsEXT,它不适用于Windows版本.所以我需要#ifdef让APPLE使用所需的东西.glBeginTransformFeedback和glBeginTransformFeedbackEXT也存在同样的问题.
但是都接受glProgramParameteriEXT,在那里我不需要干扰......
我明白,只有变换反馈,我才有问题,但......这是什么一回事?
我以为我理解OpenGL扩展如何工作,但我开始失去这种理解.
我认为当我在另一个Windows系统或另一个mac系统或另一个Linux系统上运行代码时,我会遇到新问题,因为有不同的图形适配器或其他东西.
任何人都可以帮我理解这个吗?我已阅读有关扩展的OpenGL手册,所以我遗漏了一些明显的东西.如何确保我的代码始终有效?
编辑:通过完全从Mac版本中删除GLEW并完全使用Mac自己的OpenGL 3.2实现,所有的命名都是正常的,我可以从我的着色器中完全删除#extension GL_EXT_gpu_shader4:enable.现在唯一让我担心的是,对于几何着色器,我需要函数glProgramParameteri,它似乎不存在,但是glProgramParameteriEXT.出于某种原因,此功能也适用于Windows.为什么?我可以确定它适用于所有系统/硬件吗?
我正在尝试对立方体内的球体进行光线追踪。立方体由 12 个具有法线的三角形简单构成。
立方体具有单位坐标和单位法线。因此,在其局部空间内(-1 和 1 之间),应该有一个半径为 0.5 的球体。
所以我想我应该在顶点着色器中计算光线:光线原点是插值顶点位置,光线方向是顶点法线(或其相反方向,但我认为这并不重要)。剩下的应该由插值完成。
然后在片段着色器中,我应该计算光线球体交点,如果有的话,更改片段的颜色。
在立方体的正面和背面,结果似乎是正确的,但在左侧、右侧、顶部和底部,结果似乎来自错误的角度。我应该始终看到中间的球体,而那些侧面的情况并非如此。
有人可以告诉我我做错了什么吗?
这是着色器代码:
顶点着色器:
#version 400
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNor;
uniform mat4 uProj;
uniform mat4 uView;
uniform mat4 uModel;
out vec3 vRayPos;
out vec3 vRayDir;
void main(void)
{
gl_Position = uProj * uView * uModel * vec4(aPos, 1);
vRayPos = aPos;
vRayDir = inverse(mat3(uModel)) * aNor;
}
Run Code Online (Sandbox Code Playgroud)
片段着色器:
#version 400
in vec3 vRayPos;
in vec3 vRayDir;
out vec4 oFrag;
void main(void) …Run Code Online (Sandbox Code Playgroud) 我对随机生成器的经验几乎为零。我在 C 中使用了标准 rand 函数,并且使用了柏林噪声。
但现在,我需要一个分辨率为 NxNxN(N 可能为 1e6 或更大)的立方体,其中充满白噪声(没有柏林平滑度或其他任何东西),其中我可以“选择”一个值,如果我重新选择相同的值,它应该是每次都是相同的结果。它应该被播种,这样如果我再次启动应用程序,结果需要相同。它不应该是安全的或其他什么,只是足够随机,以至于人类不应该能够仅通过思考来预测值。如果他真的用电脑分析的话,是可以预测的。
就像我会使用标准的 C rand 函数,设置种子并为 3 维执行嵌套 for 循环,并每次生成一个随机数,直到到达坐标。这当然是非常慢的。我需要快速的东西!
我在互联网上搜索过,但同时发现了很多却什么也没有。也许我正在寻找错误的关键字,但我还没有找到任何可以使用的东西。
有人可以帮助我开始吗?代码?一条链接?我并不真正关心我是否理解算法,但它应该易于实现和使用,而且应该特别快。
基于以下资源,我一直试图让GPU上的分辨率独立立方贝塞尔渲染工作:
但正如Curvy Blues网站所述,其他两个网站的文档中存在错误.Curvy Blues告诉我看看评论,但我似乎无法找到这些评论.某个地方的另一个论坛告诉我同样的事情,我不记得那个论坛是什么.但肯定有一些我想念的东西.
无论如何,我试图重新发生正在发生的事情,我无法理解从变换坐标组合的决定因素计算判别式的部分.
所以我有原始坐标,我将它们粘贴在4x4矩阵中,用M3矩阵转换这个矩阵并得到C矩阵.然后我从C矩阵的坐标创建3x3矩阵并计算行列式,然后可以将它们组合起来创建二次方程的a,b和c,这将帮助我找到根.
问题是,当我这样做时:判别式是不正确的.我清楚地把蛇形的坐标(一个对称的,但是一个正确的蛇形)放在坐标中,但它说它是一个尖点.当我自己使用wxMaxima计算它,导出第1和第2阶然后计算交叉乘积,简化为二次方程时,当我放入相同的坐标时,该方程的判别似乎是正确的.当我强制代码使用我自己的判别式来确定它是否是蛇形时,但是我使用行列式来计算更多的k,l,m纹理坐标,结果也是不正确的.所以我认为决定因素中肯定存在错误.
任何人都可以帮我解决这个问题吗?
我试图在片段着色器中的网格上进行光线跟踪.我已经编写了下面的着色器来执行此操作(顶点着色器只绘制一个screenquad).
#version 150
uniform mat4 mInvProj, mInvRot;
uniform vec4 vCamPos;
varying vec4 vPosition;
int test(vec3 p)
{
if (p.x > -4.0 && p.x < 4.0
&& p.y > -4.0 && p.y < 4.0
&& ((p.z < -4.0 && p.z > -8.0) || (p.z > 4.0 && p.z < 8.0)))
return 1;
return 0;
}
void main(void) {
vec4 cOut = vec4(0, 0, 0, 0);
vec4 vWorldSpace = mInvRot * mInvProj * vPosition;
vec3 vRayOrg = vCamPos.xyz;
vec3 vRayDir = normalize(vWorldSpace.xyz); …Run Code Online (Sandbox Code Playgroud) 这应该是简单的,它可能是,但在我的C代码中,我想在开始迭代之前知道表的大小.我需要预先分配一些内存来存储来自该表的值.
我把这个表作为lua c函数中的参数.
static int lua_FloatArray(lua_State *L)
{
int n = lua_gettop(L);
if (n != 1 || lua_gettype(L, 1) != LUA_TTABLE)
{
luaL_error(L, "FloatArray expects first parameter to be a table");
return 0;
}
int tablesize = ????;
float *a = (float*)lua_newuserdata(L, tablesize * sizeof(float));
lua_pushnil(L);
int x = 0;
while (lua_next(L, index) != 0)
{
a[x++] = (float)lua_tonumber(L, -1);
lua_pop(L, 1); // Remove value, but keep key for next iteration
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
tablesize?如何获得表格?
我试图在opengl中创建一个简单的3D数组可视化.3D阵列包含颜色值.为了实现这一点,我可以绘制很多立方体,给它们纹理坐标指向正确的纹理像素.好吧,我试过了,它的确有效.但我需要更多,而实现我想要的唯一方法是,如果我只是在平面打开时在另一个轴方向上的每个网格上绘制完整的2D平面,并且这是6个方向.例如:我在-15到+15之间绘制XY平面,在Z坐标-15到+15之间绘制XY平面,对于背面XY平面,YZ平面,背面YZ平面,......这样,我可以在每个角落放置3D纹理坐标,插值应该完成其余的工作.
我已经将数组坐标作为纹理坐标,介于0和32之间,原因是,在着色器中,我可以将纹理坐标放下,然后将其除以32,以获得网格上每个像素的精确纹理像素.
但是唉...像素着色器一直在怀疑选择,一个像素映射到与下一个像素不同的纹理像素,而下一个像素着色器再次正确映射.
我曾经通过向浮点数添加0.5或0.35来解决这些问题,以确保浮点数在所有硬件平台上都能正确舍入,但对我来说这似乎仍然是一个黑客攻击.此外,它不适用于3D纹理.
有谁能告诉我如何处理这个?
glsl ×3
opengl ×3
c ×2
raytracing ×2
3d-texture ×1
bezier ×1
cocoa ×1
cubic ×1
drawing ×1
glew ×1
gpu ×1
grid ×1
lua ×1
mapping ×1
message-loop ×1
performance ×1
random ×1
resolution ×1
seed ×1
shader ×1
trace ×1
windows ×1