OBS image-source插件
+ -

gs_draw

2024-07-08 5 0

gs_draw(GS_TRISTRIP, 0, 0);
最终调用的是device_draw函数:

void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
                  uint32_t start_vert, uint32_t num_verts)

{
    try {
        if (!device->curVertexShader)
            throw "No vertex shader specified";

        if (!device->curPixelShader)
            throw "No pixel shader specified";

        if (!device->curVertexBuffer && (num_verts == 0))
            throw "No vertex buffer specified";

        if (!device->curSwapChain && !device->curRenderTarget)
            throw "No render target or swap chain to render to";

        //设直渲染目标像
        device->FlushOutputViews();

        gs_effect_t *effect = gs_get_effect();
        if (effect)
            gs_effect_update_params(effect);

        device->LoadVertexBufferData();  //IASetVertexBuffers
        device->UpdateBlendState();  //OMSetBlendState
        device->UpdateRasterState();  //光栅化配置
        device->UpdateZStencilState(); //OMSetDepthStencilState
        device->UpdateViewProjMatrix();
        device->curVertexShader->UploadParams();//顶点着以器参数
        device->curPixelShader->UploadParams(); //像系着色器参数

    } catch (const char *error) {
        blog(LOG_ERROR, "device_draw (D3D11): %s", error);
        return;

    } catch (const HRError &error) {
        blog(LOG_ERROR, "device_draw (D3D11): %s (%08lX)", error.str,
             error.hr);
        LogD3D11ErrorDetails(error, device);
        return;
    }


    //转换为d3d11的绘制模式
    D3D11_PRIMITIVE_TOPOLOGY newTopology = ConvertGSTopology(draw_mode);
    if (device->curToplogy != newTopology) {
        device->context->IASetPrimitiveTopology(newTopology);
        device->curToplogy = newTopology;
    }

    if (device->curIndexBuffer) {
        if (num_verts == 0)
            num_verts = (uint32_t)device->curIndexBuffer->num;
        device->context->DrawIndexed(num_verts, start_vert, 0);
    } else {
        if (num_verts == 0)
            num_verts = (uint32_t)device->curVertexBuffer->numVerts;
        device->context->Draw(num_verts, start_vert);
    }
}

gs_get_effect就是获取当前的effect

gs_effect_t *gs_get_effect(void)
{
    if (!gs_valid("gs_get_effect"))
        return NULL;
    return thread_graphics ? thread_graphics->cur_effect : NULL;
}

并使用gs_effect_update_params将effect上的参数更新上到着色器中。

这里比较重要的就是FlushOutputViews。

void gs_device::FlushOutputViews()
{
    if (curFramebufferInvalidate)
    {
        ID3D11RenderTargetView *rtv = nullptr;
        if (curRenderTarget)
        {
            const int i = curRenderSide;
            rtv = curFramebufferSrgb  ? curRenderTarget->renderTargetLinear[i].Get()   : curRenderTarget->renderTarget[i].Get();
            if (!rtv) 
            {
                blog(LOG_ERROR,   "device_draw (D3D11): texture is not a render target");
                return;
            }
        }

        ID3D11DepthStencilView *dsv = nullptr;
        if (curZStencilBuffer)
            dsv = curZStencilBuffer->view;

        context->OMSetRenderTargets(1, &rtv, dsv);
        curFramebufferInvalidate = false;
    }
}

而curRenderTarget是通过device_set_render_target_internal设置的。

static void device_set_render_target_internal(gs_device_t *device,
                          gs_texture_t *tex,
                          gs_zstencil_t *zstencil,
                          enum gs_color_space space)
{
    //只有在渲染display时,会调用display的gs_load_swapchain
    if (device->curSwapChain)
    {
        if (!tex)
            tex = &device->curSwapChain->target;
        if (!zstencil)
            zstencil = &device->curSwapChain->zs;
    }

    if (device->curRenderTarget == tex &&  device->curZStencilBuffer == zstencil)
    {
        device->curColorSpace = space;
    }

    if (tex && tex->type != GS_TEXTURE_2D)
    {
        blog(LOG_ERROR,  "device_set_render_target_internal (D3D11): texture is not a 2D texture");
        return;
    }

    gs_texture_2d *const tex2d = static_cast<gs_texture_2d *>(tex);
    if (device->curRenderTarget != tex2d || device->curRenderSide != 0 || device->curZStencilBuffer != zstencil)
    {
        device->curRenderTarget = tex2d;
        device->curZStencilBuffer = zstencil;
        device->curRenderSide = 0;
        device->curColorSpace = space;
        device->curFramebufferInvalidate = true;
    }
}

二次被封装为:

void device_set_render_target(gs_device_t *device, gs_texture_t *tex,
                  gs_zstencil_t *zstencil)
{
    device_set_render_target_internal(device, tex, zstencil, GS_CS_SRGB);
}

void device_set_render_target_with_color_space(gs_device_t *device,
                           gs_texture_t *tex,
                           gs_zstencil_t *zstencil,
                           enum gs_color_space space)
{
    device_set_render_target_internal(device, tex, zstencil, space);
}

void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swapchain)
{
    gs_texture_t *target = device->curRenderTarget;
    gs_zstencil_t *zs = device->curZStencilBuffer;
    bool is_cube =
        device->curRenderTarget
            ? (device->curRenderTarget->type == GS_TEXTURE_CUBE)
            : false;

    if (device->curSwapChain) {
        if (target == &device->curSwapChain->target)
            target = NULL;
        if (zs == &device->curSwapChain->zs)
            zs = NULL;
    }

    device->curSwapChain = swapchain;

    if (is_cube) {
        device_set_cube_render_target(device, target,
                          device->curRenderSide, zs);
    } else {
        const enum gs_color_space space = swapchain ? swapchain->space
                                : GS_CS_SRGB;
        device_set_render_target_internal(device, target, zs, space);
    }
}

如render_main_texture就是通过调用device_set_render_target_with_color_space设置的渲染纹理: https://www.pnpon.com/article/detail-709.html

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!