小编Mic*_* IV的帖子

计算任意网格的平面UV坐标

我有从2d形状生成三角形网格的代码.因为在大多数情况下这些形状在表面上具有不均匀的顶点分布,所以我产生UV的问题,因此它不会导致纹理变形.任何人都可以建议一些文章,书籍,代码样本谈论平面网格上的紫外线计算技术?谢谢

3d uv-mapping

7
推荐指数
1
解决办法
4793
查看次数

创建跨平台OpenGL屏幕外上下文

我有一个任务是在C++中为Window和Linux实现屏幕外OpenGL渲染器.我已经使用LWJGL lib用Java编写了这样的版本.我使用了PBuffer对象,它根据使用的OS创建了Pbuffers.首先我想到的重新实现完整的PBuffer创建逻辑就像我在LWJGL的原生源中完成一样.然后我在StackOverflow.com上阅读这篇文章,建议使用标准上下文创建,让我们说使用GLFW(这是跨平台)但是不要创建实际的窗口.这是正确的方法吗?在这种情况下使用Pbuffer的利弊是什么?

更新: 我只想强调我使用FBO渲染帧,所以我的问题不在于如何在屏幕外模式下渲染,而是如何在Windows和Linux操作系统中创建没有窗口的上下文.

c++ opengl

7
推荐指数
1
解决办法
3719
查看次数

何时使用纹理视图

我正在阅读红皮书中的纹理视图.在页面322上说:

OpenGL允许您在多个纹理之间共享单个数据存储,每个纹理都有自己的格式和尺寸.

(通过纹理视图)

现在,我的问题是:

是否意味着单个纹理源被多个实例引用(在这种情况下是纹理视图)?

它与使用相同的纹理对象有何不同,例如使用不同的采样器?

此外,是否意味着通过纹理视图更改纹理像素会改变原始纹理对象中的像素?(我认为答案是肯定的,因为doc说它是纹理存储的别名)

opengl opengl-4

7
推荐指数
1
解决办法
1361
查看次数

使用几何着色器将渲染分层渲染到CUBEMAP

我试图用一个drawcall渲染到立方体贴图的所有6个面.GL立方体贴图附加到一个屏幕外的帧缓冲对象.我得到的结果只是面部数字零受到帧缓冲清晰颜色和片段的影响着色器输出.目标是使用被调用6次的几何着色器(每个面一次),然后将gl_InstanceID分配给内置的gl_Layer.Fragment着色器阶段将读取gl_Layer值并基于in来遮蔽栅格.它是预期的所有6面临的将涂上一个独特的颜色,取决于gl_Layer值.

为了让测试看到我得到正确的gl_layer值,我试图通过以下片段着色器将图层ID渲染到纹理的alpha通道中:

#version 430  

// Ouput data
layout(location = 0) out vec4 color;

in int gl_Layer;

void main(){
    color  = vec4(0.5,0.5,0.5,float(gl_Layer)/255.0);
}
Run Code Online (Sandbox Code Playgroud)

顶点着色器基本上什么都不做:

#version 430  

in vec3 position;


void main(){
     gl_Position = vec4(position, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

并且几何着色器执行6次,渲染单位正方形(覆盖整个视口)并根据gl_InvocationID设置gl_Layer:

#version 430  

layout(triangles, invocations = 6) in;
layout(triangle_strip, max_vertices = 4) out;

out int gl_Layer;

void main() 
{     
    const vec2 vert_data[4] = vec2[]( vec2(-1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, 1.0), vec2(1.0, -1.0) );

    for(int i=0; i<4; i++)
    {
        gl_Layer = gl_InvocationID;
        gl_Position = vec4(vert_data[i].xy,0,1);
        EmitVertex(); …
Run Code Online (Sandbox Code Playgroud)

opengl glsl

7
推荐指数
1
解决办法
1248
查看次数

内存屏障无法通过CUDA在计算阶段和数据访问之间同步

我有以下管道:

  1. 渲染到自定义FBO的纹理附件.
  2. 将纹理附件绑定为图像.
  3. 运行计算着色器,使用imageLoad/Store从上面的图像中进行采样.
  4. 将结果写入SSBO或图像.
  5. 将SSBO(或图像)映射为CUDA CUgraphicsResource,并使用CUDA处理来自该缓冲区的数据.

现在,问题在于在阶段4和5之间同步数据.以下是我尝试过的同步解决方案.

glFlush - 并不真正起作用,因为它不能保证所有命令执行的完整性.

glFinish - 这个有效.但不推荐使用它,因为它最终确定了提交给驱动程序的所有命令.

ARB_sync 这里有人说它不推荐使用,因为它会严重影响性能.

glMemoryBarrier这个很有意思.但它根本行不通.

以下是代码示例:

glMemoryBarrier(GL_ALL_BARRIER_BITS);
Run Code Online (Sandbox Code Playgroud)

并尝试过:

glTextureBarrierNV()
Run Code Online (Sandbox Code Playgroud)

代码执行如下:

 //rendered into the fbo...
  glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
  glBindImageTexture(imageUnit1, fboTex, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA8); 
  glBindImageTexture(imageUnit2, imageTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8));
  glDispatchCompute(16, 16, 1);

  glFinish(); // <-- must sync here,otherwise cuda buffer doesn't receive all the data

 //cuda maps the image to CUDA buffer here..
Run Code Online (Sandbox Code Playgroud)

此外,我尝试在启动计算之前从上下文中取消绑定FBO和取消绑定纹理,我甚至尝试使用glMemoryBarrier它们之间的集合启动一个计算,然后从第一次计算启动到CUDA获取目标图像.仍然没有同步.(嗯,这是有道理的,因为两个计算也彼此不同步)

在计算着色器阶段之后.它没有同步!只有当我更换glFinish或完全停止管道的任何其他操作时.比如glMapBuffer(),例如.

那么我应该使用glFinish(),还是我在这里遗漏了什么?为什么glMemoryBarrier()在CUDA接管控制之前不同步计算着色器工作?

UPDATE

我想稍微重构一下这个问题,因为原来的问题已经很久了.尽管如此,即使使用最新的CUDA和视频编解码器SDK(NVENC),问题仍然存在.所以,我不关心为什么glMemoryBarrier …

opengl cuda nvenc

7
推荐指数
1
解决办法
380
查看次数

当自动生成mipmap时,glTexStorage2D是否必不可少

我使用gltexSubImage2D()更新到OpenGL 4.0中的texture2D.纹理使用自动生成的mipmap生成

 glGenerateMipmap(GL_TEXTURE_2D); 
Run Code Online (Sandbox Code Playgroud)

我的纹理更新失败,直到我明白我必须在更新时重新生成mipmap (或删除mipmaps生成).然后我读了这个 wiki,当生成mipmap时有一个glTexStorage2D的用法.我实际上从来没有注意过这个方法.所以我我想知道每次使用mipmap生成纹理时是否必须使用它?

更新:

我从方法规格中看出它

同时指定二维纹理或一维纹理阵列的所有级别的存储要求

我想在使用它时应该会在生成mipmap时提高性能吗?这是真的吗?

opengl opengl-4

6
推荐指数
2
解决办法
4622
查看次数

使用FFMPEG API读取特定视频帧

我使用这个循环从FFMPEG中的视频流中读取帧:

while(av_read_frame(pFormatCtx, &packet)>=0) {
        // Is this a packet from the video stream?
        if(packet.stream_index==videoStream) {
            // Decode video frame
            avcodec_decode_video2(pCodecCtx,pFrame,&frameFinished,&packet);

            // Did we get a video frame?
            if(frameFinished) {


                sws_scale(img_convert_context ,pFrame->data,pFrame->linesize,0,
                     pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize);
                printf("%s\n","Frame read finished ");

                                       ExportFrame(pFrameRGBA->data[0]);
                    break;
                }
            }
            // Save the frame to disk

        }
            printf("%s\n","Read next frame ");

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }
Run Code Online (Sandbox Code Playgroud)

所以通过这种方式顺序读取流.我想要的是随机访问帧以便能够读取特定帧(按帧号).如何完成?

c++ ffmpeg

6
推荐指数
1
解决办法
1万
查看次数

最新的GCC中是否提供C++ 11 <codecvt>标头?

看完后<codecvt>不是一个标准的头?我不知道该怎么做,因为我的Windows版本的代码库用于<codecvt>在宽字符串和字符串之间进行转换.我目前使用GCC 4.7 for Linux版本的代码.难道<codecvt>还缺少最新的GCC?什么是解决方法?

顺便说一下,正如这里所说,以下代码不适用于GCC:

wstring ws = L"hello";
string ns(ws.begin(), ws.end());
Run Code Online (Sandbox Code Playgroud)

c++ gcc c++11

6
推荐指数
1
解决办法
1747
查看次数

FFMPEG:av_rescale_q - time_base差异

我想一劳永逸地知道,在FFMPEG中,时基收费和重新缩放是如何工作的.在回答这个问题之前,我做了一些研究,发现了许多有争议的答案,这使得它更加令人困惑.因此,根据官方的FFMPEG 示例,我们必须这样做

从编解码器到流时基的rescale输出数据包时间戳值

用这样的东西:

pkt->pts = av_rescale_q_rnd(pkt->pts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt->dts = av_rescale_q_rnd(pkt->dts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt->duration = av_rescale_q(pkt->duration, *time_base, st->time_base);
Run Code Online (Sandbox Code Playgroud)

但是在这个问题中,一个人向我提出类似的问题,他给出了更多的例子,他们每个人都做了不同的事情.与所有这些方式都很好的答案相反,对我来说,只有以下方法有效:

frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我在FFMPEG API外以60 fps生成视频数据包(h264),然后将它们写入mp4容器.

我明确地说:

video_st->time_base = {1,60};
video_st->r_frame_rate = {60,1};
video_st->codec->time_base = {1 ,60};
Run Code Online (Sandbox Code Playgroud)

我看到的第一个奇怪的事情发生在我为输出格式上下文写入标题之后:

AVDictionary *opts = nullptr;
int ret = avformat_write_header(mOutputFormatContext, &opts);
av_dict_free(&opts);
Run Code Online (Sandbox Code Playgroud)

之后,video_st->time_base填充:

num = 1;
den = 15360
Run Code Online (Sandbox Code Playgroud)

我不明白为什么.

我想要有人请我说.接下来,在写帧之前,我计算了数据包的PTS.在我的情况下PTS = DTS,因为我根本不使用B帧.

我必须这样做:

 const int64_t duration = av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
 totalPTS += duration; //totalPTS …
Run Code Online (Sandbox Code Playgroud)

c++ video ffmpeg libav

6
推荐指数
1
解决办法
1715
查看次数

Vulkan API:支持的最大 MSAA 样本为 VK_SAMPLE_COUNT_8_BIT

我正在编写基于 Vulkan API 的渲染器。目前我正在尝试为颜色附件添加 MSAA。我很确定我可以使用VK_SAMPLE_COUNT_16_BIT ,但 limits.framebufferColorSampleCounts返回允许 MSAA 级别高达VK_SAMPLE_COUNT_8_BIT(含)的位标志

我在全新的 NVIDIA QUADRO RTX 3000 卡上运行。我还使用最新的 NVIDIA 驱动程序:441.28 我检查了 OpenGL 和 GPU 上限查看器显示中的限制

GL_MAX_FRAMEBUFFER_SAMPLES = 32

这有什么意义呢?该限制仅由 Vulkan API 规定吗?如果硬件不支持超过 x8,那么这是否意味着 OpenGL 驱动程序在 CPU 上模拟它,例如通过超级采样之类的东西?这就是 khronosdev.slack 的几位渲染开发人员对我所说的话?是否有意义?供应商是否必须按照标准进行编译,然后要么以正确的方式实施 MSAA,要么根本不实施?

有没有可能 OpenGL 并不“真正”支持超过 x8 MSAA,但驱动程序通过超级采样之类的东西来模拟它?

更新

本页解释了 OpenGL 的 MSAA 实现的整个状态,实际上,从中可以清楚地了解为什么 Vulkan 不在我的卡上提供超过 x8 的样本。这是妙语:

一些 NVIDIA 驱动程序支持多重采样模式,这些模式在内部实现为多重采样和自动超级采样的组合,以获得比硬件直接支持的更高级别的抗锯齿效果。

nvidia msaa vulkan

6
推荐指数
1
解决办法
1248
查看次数

标签 统计

opengl ×5

c++ ×4

ffmpeg ×2

opengl-4 ×2

3d ×1

c++11 ×1

cuda ×1

gcc ×1

glsl ×1

libav ×1

msaa ×1

nvenc ×1

nvidia ×1

uv-mapping ×1

video ×1

vulkan ×1