我正在为每个帧使用JPEG压缩技术编码视频编解码器.直到这里我已经编码了YUV,DCT和量化DCT(编码和解码).我已经编码了YUV422编码,但我不明白如何进行反向(解码).
为了计算每个像素的YUV,我使用了以下等式:
编码:
Y = 0.299 * R + 0.587 * G + 0.114 * B
U = -0.1687 * R - 0.4187 * G + 0.5 * B + 128
V = 0.5 * R - 0.4187 * G - 0.0813 * B + 128
Run Code Online (Sandbox Code Playgroud)
解码:
R = Y + 1.402 * (V - 128)
G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)
B = Y + 1.772 * (U - 128) …Run Code Online (Sandbox Code Playgroud) 我使用SDL 2.0编写了一个简单的SDL程序.当我想检查鼠标滚轮事件时,我有一点问题.实际上,在版本2.0中,标志SDL_BUTTON_WHEELDOWN和SDL_BUTTON_WHEELUP不再存在.只有标志SDL_MOUSEWHEEL.下面的代码正确检查'WHEELUP'和'WHEELDOWN'事件但具有相同的标志.
while(!terminer)
{
while (SDL_PollEvent(&evenements))
{
switch (evenements.type)
{
case SDL_QUIT:
terminer = true;
break;
case SDL_KEYDOWN:
switch (evenements.key.keysym.sym)
{
case SDLK_ESCAPE:
terminer = true;
break;
}
break;
case SDL_MOUSEMOTION:
std::cout << "MOUSE : MOVE" << std::endl;
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
std::cout << "MOUSE : BUTTON DOWN" << std::endl;
break;
case SDL_MOUSEWHEEL:
std::cout << "MOUSE : WHEEL" << std::endl;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
但我想分别处理'WHEELUP'和'WHEELDOWN'事件.在我的情况下我尝试了其他几个旗帜但没有成功.有人能帮帮我吗?
我写了一个非常简单的OpenGL应用程序.它的目标是加载纹理并将其绘制在平面上.如果我使用函数'glTexSubImage2D',则平面没有纹理,函数'glGetError'返回错误'1281'(无效值).但是,如果我使用'glTexImage2D'函数,我的平面纹理正确(我没有错误).
这是我的一段代码:
void core::RootDevice::LoadTexture(char const *pFileName)
{
SDL_Surface *pSurface = IMG_Load(pFileName);
char *pPixels = reinterpret_cast<char*>(pSurface->pixels);
uint32_t bytePerPixel = pSurface->format->BitsPerPixel;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID);
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pSurface->w, //NO ERROR : All is ok
//pSurface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, pPixels);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pSurface->w, //ERROR : 1281
pSurface->h, GL_RGB, GL_UNSIGNED_BYTE, pPixels);
std::cout << glGetError() << std::endl;
getchar();
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
Run Code Online (Sandbox Code Playgroud)
并且渲染代码: …
我没有找到任何解释如何使用 OpenGL 缩小纹理的教程。
例如,如果我有一个 1024x720 的纹理,我想按 1/4 的因子生成缩小比例,该怎么做?
更新
我在片段着色器中尝试了以下过滤代码:
vec4 DownSampleFrame(sampler2D uniformSampler)
{
vec2 pixelOffset = vec2(1.0f/1024.0f, 1.0f/720.0f);
vec3 downScaleColor = vec3(0.0f);
{
downScaleColor += texture(uniformSampler, vec2(TexCoords.x - 4.0f * pixelOffset.x, TexCoords.y)).xyz;
downScaleColor += texture(uniformSampler, vec2(TexCoords.x + 4.0f * pixelOffset.x, TexCoords.y)).xyz;
downScaleColor += texture(uniformSampler, vec2(TexCoords.x, TexCoords.y - 4.0f * pixelOffset.y)).xyz;
downScaleColor += texture(uniformSampler, vec2(TexCoords.x, TexCoords.y + 4.0f * pixelOffset.y)).xyz;
downScaleColor *= 0.25f;
}
return (vec4(downScaleColor, 1.0f));
}
Run Code Online (Sandbox Code Playgroud)
这种代码是指下采样算法吗?
我做了很多关于如何将顶点数据收集到通常称为批次的组中的研究。
对我来说,这是关于该主题的两篇主要有趣的文章:
https://www.opengl.org/wiki/Vertex_Specification_Best_Practices
http://www.gamedev.net/page/resources/_/technical/opengl/opengl-batch-rendering-r3900
Run Code Online (Sandbox Code Playgroud)
第一篇文章解释了如何操作 VBO 的最佳实践(最大大小、格式等)。
第二个提供了一个关于如何使用批处理管理顶点内存的简单示例。根据作者的说法,每个批次必须包含一个 VBO 实例(加上 VAO),并且他强烈坚持这样一个事实:VBO 的最大大小范围在 1Mo(1000000 字节)到 4Mo(4000000 字节)之间。第一篇文章提出了同样的建议。我引用“根据一份 nVidia 文档,1MB 到 4MB 是一个不错的大小。驱动程序可以更轻松地进行内存管理。对于所有其他实现以及 ATI/AMD、Intel、SiS 来说,情况应该相同。”
我有几个问题:
1)上面提到的最大字节大小是绝对规则吗?分配比 4Mo(例如 10 Mo)更重要的字节大小的 VBO 是否那么糟糕?
2) 对于总顶点字节大小大于 4Mo 的网格我们该怎么办?我需要将几何体分成几批吗?
3)一个批次是否不可避免地存储为一个唯一的VBO属性,或者多个批次可以存储在一个VBO中?(这是两种不同的方式,但第一种似乎是正确的选择)。你同意吗?
根据作者的说法,每个批次处理一个最大尺寸在 1 到 4 Mo 之间的唯一 VBO,并且整个 VBO 必须仅包含共享相同材质和变换信息的顶点数据。因此,如果我必须使用不同的材质对其他网格进行批处理(因此顶点无法与现有浴合并),我必须使用实例化的新 vbo 创建一个新批次。
因此,根据作者的说法,我的第二种方法是不正确的:不建议将多个批次存储到单个 VBO 中。
渲染复杂网格物体的最佳方法是什么?我在下面写了不同的解决方案,并想知道你对它们有什么看法.
我们举一个例子:如何渲染'Crytek-Sponza'网格?
PS:我不使用Ubershader但只使用单独的着色器
如果您在以下链接下载网格:
http://graphics.cs.williams.edu/data/meshes.xml
Run Code Online (Sandbox Code Playgroud)
并且在Blender中加载它你会看到整个网格分别由大约400个子网格和自己的材质/纹理组成.
虚拟渲染器(版本1)将分别渲染400个子网格中的每一个!它意味着(为了简化情况)400个绘制调用,每个调用都绑定到一个材质/纹理.性能非常糟糕.非常慢!
pseudo-code version_1:
foreach mesh in meshList //400 iterations :(!
mesh->BindVBO();
Material material = mesh->GetMaterial();
Shader bsdf = ShaderManager::GetBSDFByMaterial(material);
bsdf->Bind();
bsdf->SetMaterial(material);
bsdf->SetTexture(material->GetTexture()); //Bind texture
mesh->Render();
Run Code Online (Sandbox Code Playgroud)
现在,如果我们处理正在装载的材料,我们可以注意到Sponza仅在现实中组成(如果我有一个很好的记忆:) :) 25种不同的材料!
因此,更智能的解决方案(版本2)应该是批量收集所有顶点/索引数据(在我们的示例中为25),而不是将VBO/IBO存储到子网格类中,而是存储到名为Batch的新类中.
pseudo-code version_2:
foreach batch in batchList //25 iterations :)!
batch->BindVBO();
Material material = batch->GetMaterial();
Shader bsdf = ShaderManager::GetBSDFByMaterial(material);
bsdf->Bind();
bsdf->SetMaterial(material);
bsdf->SetTexture(material->GetTexture()); //Bind texture
batch->Render();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,每个VBO包含共享完全相同的纹理/材料设置的数据!
它好多了!现在我觉得25个VBO用于渲染的海报太多了!问题是渲染sponza的Buffer绑定数量!我认为一个好的解决方案应该是分配一个新的VBO,如果第一个如果'full'(例如让我们假设一个VBO的最大大小(在VBO类中定义为属性的值)是4MB或8MB).
pseudo-code version_3:
foreach vbo in vboList //for example 5 VBOs (depends on the maxVBOSize)
vbo->Bind();
BatchList batchList = vbo->GetBatchList(); …Run Code Online (Sandbox Code Playgroud) 我正在使用GLSL着色器开发一个程序.我用2种不同的方法编写了两种不同的方法来计算ADS(环境+漫反射+镜面反射)着色.为了正确地完成工作,我使用子程序来使用一种或另一种方法来计算ADS着色.
这是一段片段着色器代码:
subroutine vec3 LightShadingEffectType(int idx, vec3 normal, vec3 lightDir);
subroutine uniform LightShadingEffectType LightShadingEffect;
subroutine (LightShadingEffectType)
vec3 Basic_ADS_Shading(int idx, vec3 normal, vec3 lightDir)
{
vec3 reflectDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-Position.xyz);
vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;
vec3 Diffuse = LightInfos[idx].Ld * MaterialInfos.Kd * max(dot(lightDir, normal), 0.0f);
vec3 Specular = LightInfos[idx].Ls * MaterialInfos.Ks * pow(max(dot(reflectDir, viewDir), 0.0f), MaterialInfos.Shininess);
vec3 Emissive = MaterialInfos.Ke;
return (Ambient + Diffuse + Specular + Emissive);
}
subroutine (LightShadingEffectType)
vec3 Phong_ADS_Shading(int idx, vec3 normal, …Run Code Online (Sandbox Code Playgroud) 我使用OpenGL和GLSL开发了一个小型3D引擎.
我已经合并了一个顶点数据批处理系统,其目标是收集共享相同着色器程序的所有几何体(所有对象)和相同的顶点缓冲对象(VBO)中的相同转换,从而最小化状态更改(绑定)和绘制调用太.
我目前使用函数'glMultiDrawElements'来呈现特定批量的数据(所以一次绘制调用).因此,例如,如果我在我的批处理3网格中,我有3个索引数组(每个网格一个)组织在'GLvoid**'数组(双数组)中.因此,为了渲染我的3个网格,我有一个独特的glMultiDrawElements调用,但是我必须直接将参数中的double元素数组传递给函数.
但我想知道(对于性能问题)是否可以将所有元素(双元素数组)存储在索引缓冲区对象(IBO)中(就像可以使用glDrawElements一样 - >这里是一个简单的元素数组)并在glMultiDrawElements调用之前将其绑定...我不这么认为,因为它是一个双数组,而不是一个简单的数组,但也许(我希望如此)我错了.
这是使用glDrawElements(伪代码)的示例:
[...]
//Setup data
[...]
#define OFFSET_BUFFER(offset) ((char*)NULL + offset)
foreach (pMeshGeometry from meshes) //iterates for each mesh of the scene
{
pMeshGeometry->GetIndexBuffer().Lock(); //Bind IBO
{
glDrawElements(pMeshGeometry->GetPrimitiveType(),
pMeshGeometry->GetIndexBufferSize(), pMeshGeometry->GetIndexBuffer().GetType(), OFFSET_BUFFER(0)); //Render a specific mesh eccording to indices
}
}
Run Code Online (Sandbox Code Playgroud)
目前我用这种方式使用glMultiDrawElement:
glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT,
(const GLvoid **)&this->m_IndexAttribArray[0], this->m_CountElementArray.size()); //I enter the array of pointer directly in parameter
Run Code Online (Sandbox Code Playgroud)
所以,也许以下示例应该是可能的:
#define OFFSET_BUFFER(offset) ((char**)NULL + offset) //Something like this
glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT,
OFFSET_BUFFER(0), this->m_CountElementArray.size()); //Something like this
Run Code Online (Sandbox Code Playgroud)
所以,如果不可能这样做,我会想到函数'glDrawRangeElements'.对于我的3个网格到一个独特的VBO的例子,我只需要在每个glDrawRangeElements调用之前绑定一个IBO(这里,每个网格有3个绘制调用 …
这是我的问题:
我需要计算包含在std :: map>类型的std :: map中的几个std :: vector的元素总数;
要计算元素总数,我使用以下代码:
std::map<int, std::vector<float>>::iterator vertex_It = myMap.begin();
uint32_t total_byte_size = 0;
for (; vertex_It != myMap.end(); ++vertex_It)
total_byte_size += vertex_It->second.size() * sizeof(float);
Run Code Online (Sandbox Code Playgroud)
我尝试使用std :: accumulate算法和lambda表达式,如下所示:
uint32_t total_byte_size = 0;
std::accumulate(myMap.begin(), myMap.end(),
[&total_byte_size](const uint32_t &vertex_type, const std::vector<float> &vertex_attribute) -> bool{
total_byte_size += vertex_attribute.size();
return (true);
});
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有编译.我尝试了不同的代码组合而没有成功.
对于这个简单的问题,是否存在使用std :: accumulate和lambda表达式的方法?
非常感谢您的帮助!
我正在我的程序中实现高斯模糊效果.为了完成这项工作,我需要在特定纹理中渲染第一个模糊信息(Y轴上的那个)(让我们称之为tex_1)并使用tex_1中包含的相同信息作为第二个渲染过程的输入信息(对于X轴) )填充包含最终高斯模糊结果的其他纹理(让我们称之为tex_2).
一个好的做法应该是创建2个帧缓冲区(FBO),每个缓冲区附加一个纹理,并链接到GL_COLOR_ATTACHMENT0(例如).但我只想知道一件事:
是否可以使用相同的FBO填充这2个纹理?
所以我必须启用GL_COLOR_ATTACHMENT0和GL_COLOR_ATTACHMENT1并将所需的纹理绑定到正确的渲染过程,如下所示:
伪代码:
FrameBuffer->Bind()
{
FrameBuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(); //tex_1
{
//BIND external texture to blur
//DRAW code (Y axis blur pass) here...
//-> Write the result in texture COLOR_ATTACHEMENT0 (tex_1)
}
FrameBuffer->GetTexture(GL_COLOR_ATTACHMENT1)->Bind(); //tex_2
{
//BIND here first texture (tex_1) filled above in the first render pass
//Draw code (X axis blur pass) here...
//-> Use this texture in FS to compute the final result
//within COLOR_ATTACHEMENT1 (tex_2) -> The final result
}
}
FrameBuffer->Unbind()
Run Code Online (Sandbox Code Playgroud)
但在我看来有一个问题,因为我需要每个渲染过程将外部纹理绑定为我的片段着色器中的输入.因此,纹理的第一个绑定(color_attachment)丢失了!
那么它是否存在使用一个FBO解决我的问题的方法,还是我需要使用2个独立的FBO?