Pixel Coordinates

TF坐标系变换 TF坐标系变换1. 概述2. 代码3. 最终结果4. 参考链接 1. 概述 使用代码实例来理解tf发布信息中的位姿变换具体含义:在父坐标系下描述父坐标系到子坐标系的变换关系,希望能帮助大家,同时给自己一个参考。 2. 代码 参考代码如下 #include <ros/ros.h> #include <tf/transform_broadcaster.h> int main(int argc, char** argv){ ros::init(argc, argv, "my_tf_b 阅读详情

DirectXTutorial.com

The Ultimate DirectX Tutorial

Sign In

Navigation

Home
DirectX for Windows 8
DirectX 11.2
DirectX 11.1
DirectX for Desktop
DirectX 11
DirectX 9
Useful Resources
About DirectXTutorial
DirectXTutorial Premium
Testimonials

Contact

Contact me here:
Twitter: @dastopher
Email: chris@directxtutorial.com

Or leave me feedback:
Quick Feedback

Lesson 3: Rendering Frames

Previous

Next

Lesson Overview

Once Direct3D is initialized, it's time to start doing some actual rendering. Rendering itself is very easy, but there is a little bit of preparatory work involved. In this lesson we're going to get everything set up to render a blank frame, over and over again.

The setup involved is simple. There are two things that need to be done. First, we need to tell the GPU where in memory to create the final image (for us, this is the back buffer). Second, we need to tell the GPU where on the backbuffer it should draw.

Once that's done, we can render, and man is it easy.

Setting the Render Target

Let's start with where to render to. Now logically you would say, "the backbuffer, duh!" and be done. However, Direct3D doesn't actually know that at this point. It is possible that you do not want to render to the back buffer right away. For example many games render to the surface of a model, then render that model to the back buffer. This technique can produce a variety of effects. If you have played the game Portal you will have seen an example of this. In Portal, the game engine first renders to the portal, then renders a full scene with the portal image included.

Rendering to a Portal, and Rendering to the Back Buffer



Rendering to a Portal, and Rendering to the Back Buffer

When rendering in Direct3D, you must establish the render target. This is a simple COM object that maintains a location in video memory for you to render into. In most cases (including our case) this is the back buffer.

Here's how we do it:

ID3D11RenderTargetView *backbuffer;    // global declaration

// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
    // Direct3D initialization
    // ...

    // get the address of the back buffer
    ID3D11Texture2D *pBackBuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

    // use the back buffer address to create the render target
    dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
    pBackBuffer->Release();

    // set the render target as the back buffer
    devcon->OMSetRenderTargets(1, &backbuffer, NULL);

}

Whoa. It looks complex, but it's pretty simple.

There are three things being done here. First, we determine the address of the back buffer. Second, we create a COM object using that address to represent the render target. Third, we set that object as the active render target.

There's some new code here, so let's find out what it all means.

ID3D11RenderTargetView *backbuffer;

This variable is a pointer to an object that holds all the information about the render target. We'll be rendering to the back buffer, so we'll call this variable 'backbuffer'.

ID3D11Texture2D *pBackBuffer;

In 3D rendering, a texture is another name for an image. An ID3D11Texture2D is an object that stores a flat image. Like any COM object, we first define the pointer, and later a function creates the object for us.

swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

You may not believe me, but this command is actually simple. What this GetBuffer() function does is find the back buffer on the swap chain and use it to create the pBackBuffer texture object.

The first parameter is the number of the back buffer to get. We are only using one back buffer on this chain, and it is back buffer #0. Therefore, the first parameter will be 0.

The second parameter is a number identifying the ID3D11Texture2D COM object. Each type of COM object has its own unique ID that is used to get information about it. To get this ID, we must use the __uuidof operator. The exact details of how this works are unimportant, but the reason we do it is so that the GetBuffer() function knows what type of object it is supposed to be creating.

The third parameter may not make sense to you unless you are at least intermediate with C++. Basically a void* is a pointer that points to no particular type of variable. For example, a double* points to a double, whereas an int* points to an int. A void* is used to point to anything, and it can be converted to any other type of pointer.

In this third parameter, we have a pointer to a void*. This void* gets filled with the location of the ID3D11Texture2D object. It needs to be a void* because there are other types of objects we could be asking for.

This particular function is one that you won't be messing around with too much, so don't worry if it's a little bit shrowded in mystery right now. You'll have an easier time getting it as you learn more about Direct3D.

dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);

This function creates the render target object. We created the pointer for this object at the top of the program.

The first parameter is a pointer to the texture. It should be 'pBackBuffer' for our program.

The second parameter is a struct that describes the render target. We won't need to fill this out for the back buffer. We'll just set it to NULL.

The third parameter is the address of the object pointer. The pointer name was 'backbuffer', so we'll use '&backbuffer'.

pBackBuffer->Release();

The Release() function frees all memory and closes all threads used by a COM object. We are done with the pBackBuffer object, so we will Release() it. Note that this doesn't destroy the back buffer, it only closes the texture object we used to access it.

devcon->OMSetRenderTargets(1, &backbuffer, NULL);

This last function actually sets the render target. More exactly, it sets multiple render targets.

The first parameter is the number of render targets to set. This will usually be 1, but there are cases where it will be more.

The second parameter is a pointer to a list of render target view objects. We only have one, so it's just the address of our render target object (&backbuffer).

The third parameter is advanced, and we'll get into it in a later lesson. For now it can be NULL.

This section of code is a bit complex. Make sure you go over it until you get what is happening, because it will be used and modified many times in your Direct3D programming.

Setting the Viewport

This section of code will be a piece of cake compared to the last one.

A viewport is a way of translating pixel coordinates to normalized coordinates. The following diagram shows the difference between the two.

Pixel Coordinates and Normalized Coordinates



Pixel Coordinates and Normalized Coordinates

On the left, pixel coordinates start at 0, 0 in the upper-left corner, and increase one pixel at a time. On the right, normalized coordinates start at -1, -1 and increase to 1, 1, no matter the size of the back buffer. The word normalized means that a value is adjusted until it equals 1.

What -1, -1 and 1, 1 actually equate to is determined by the viewport. The viewport is a struct that lets us set where -1, -1 and 1, 1 will be in pixel coordinates.

Here's what the code to set the viewport looks like:

// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
    // Direct3D initialization
    // ...

    // Set the render target
    // ...

    // Set the viewport
    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = 800;
    viewport.Height = 600;

    devcon->RSSetViewports(1, &viewport);

}

Probably the only line here that needs explanation is the last one.

RSSetViewports() is a function that activates viewport structs. The first parameter is the number of viewports being used, and the second parameter is the address of a list of pointers to the viewport structs.

Using multiple viewports is handy in certain advanced situations, but we won't get into them here. For now, 1 and '&viewport' will suit the parameters fine.

Rendering Frames

Next we'll create a function that renders a single frame. The frame will be rather simple for now, and will consist only of a blue background. Of course, you can change the color if you want. Here is the code for this function.

// this is the function used to render a single frame
void RenderFrame(void)
{
    // clear the back buffer to a deep blue
    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

    // do 3D rendering on the back buffer here

    // switch the back buffer and the front buffer
    swapchain->Present(0, 0);
}

Nice! A whopping two lines of code! Let's talk about what they do.

devcon->ClearRenderTargetView()

This fills a render target buffer with a specific color. In our case, we are going to fill our back buffer. It's pretty simple. There are two parameters.

The first one is the address of the render target object. We just put 'backbuffer' here.

The second parameter is the color you want to fill the back buffer with. To do this, we use a simple struct called D3DXCOLOR. The four constructor parameters are used to build the color. The first three are the red, green and blue values, and the fourth is the alpha value (which is meaningless on a backbuffer, but necessary as we'll see later on).

swapchain->Present()

Next we call the Present() function. This function is where everything that has been drawn on the back buffer actually appears. It's job is basically to perform the "swap" in the swap chain, so that the back buffer becomes the front buffer.

The two parameters, both set to 0, are not going to be used much in this tutorial.

Obligatory Cleanup

In the last lesson we closed down Direct3D by releasing each COM object we created. Most COM objects have this Release() function, and if they do, we must call it when we're done. The render target object is no exception.

// this is the function that cleans up Direct3D and COM
void CleanD3D()
{
    // close and release all existing COM objects
    swapchain->Release();
    backbuffer->Release();
    dev->Release();
    devcon->Release();
}

Get into the habit of ensuring that all COM objects are released. The more we add, the easier it can be to forget one.

The Finished Program

Excellent! We've got Direct3D running and we've got a simple, blank frame rendering into a window. We're making good progress.

Below, I've added in the new code. Take a look over it, and go ahead and run the new program.

[Main.cpp]     
 

Now that we've got a frame rendering, we should get a blue window!

Our Direct3D Program, Now in Color



Our Direct3D Program, Now in Color

Ready...Set...

Once again, let's look at what we've learned and find out if we're ready to move on.

Questions

1. What is a render target? What function creates the render target?
2. What two functions render the blank, blue frame? What do these functions do exactly?
3. What are normalized coordinates?

Exercises

1. See if you can get your program to change colors while running. Make it fade from blue to black.
2. Change the viewport and see what "happens". We'll discuss why this is in a few lessons.

Next Lesson: Going Fullscreen

三维重建系列之:世界坐标系、相机坐标系和像素坐标系的基本概念和相互转换 本文介绍了计算机视觉中使用的三个主要坐标系:世界坐标系、相机坐标系和像素坐标系。文章详细阐述了这些坐标系的定义、重要性以及它们之间的转换方法。通过结合外参矩阵和内参矩阵,我们展示了如何从一个坐标系准确地转换到另一个坐标系,从而为实际应用中的图像处理和三维空间分析提供数学基础。 阅读详情

相关推荐

【遥感图像】像素坐标(Pixel Coordinates)

像素坐标(Pixel Coordinates) "Hello world"中创建的窗口,由屏幕上的小方格组成,我们称之为像素。默认为黑色,当然可以设置为别的颜色。下图是一个8像素 X 8像素(宽 * 高)的对象: 可以通过笛卡尔坐标系,X列,Y行,来找到每一个像素的位置。(4,0),(2,2),(0,5)和(5,6)处的像素被涂成黑色,像素在(2,4)处被涂成灰色,而所有其他像素都被涂成白色。XY坐标也称为点。 ...

小苏打的学习博客 3727

从像素坐标到相机坐标_多视图几何基础——深入理解相机内外参数

上一篇:前言(comming soon)关键词:相机模型,多视图几何,相机内参数,相机外参数,skew畸变1. 针孔相机模型Figure 1针孔相机模型是一种理想化的简单相机模型,也是成像的最基本原理,在这种模型中,有一个暗室,暗室中有一个足够小的针孔,外部世界的光线通过这个针孔进入暗室盒子,光线投射到暗室盒子中的二维平面,即将一个三维的场景(Scene)映射成了一张二维的影像。这个针孔到成像平面...

weixin_39782752的博客 970

从多项式到神经网络:DPD算法演进史及其在RRU中的工程实现

本文系统梳理了数字预失真(DPD)算法从经典多项式模型、查表法到神经网络驱动的演进历程,并深入探讨了其在基站射频单元(RRU)中面临的硬件资源约束与工程实现挑战。文章为通信设备的技术决策者提供了算法选型、性能权衡及混合架构设计的实用评估框架,助力在性能、功耗与成本间找到最优平衡。

cherry的博客 1076

[Unity]屏幕空间(视口)坐标(viewport coordinate)的几种计算方法对比分析

前言: 本本的主要目的在于对比分析几种计算屏幕空间坐标的方法,顺便梳理了一遍坐标在不同阶段的变换。其中特别对比了SV_Postion语义及TEXCOORD0传递参数的异同,同时分析了ComputeScreenPos这个怪异的函数的本质。 运行环境: Unity 2019.4.10f1 Graphics API: Direct3D11 效果图: 代码: 本文的说明主要与代码相结合,下面的几种方法都亲测可用。 // https://blog.youkuaiyun.com/coffeecato /.

coffeecato的个人博客 2962

Rockchip rv1126平台在gstreamer1中添加OpenCv实现视频流负片的效果

rv1126 gstreamer opencv negetive effect

Aisy_D的专栏 1463

VC Spyglass实战指南:从零开始掌握CDC约束配置与调试

本文详细介绍了如何使用VC Spyglass进行CDC约束配置与调试,从基础环境搭建到典型CDC问题调试实战,帮助开发者快速掌握跨时钟域验证技术。通过TCL脚本和SDC约束的深度解析,提升CDC验证效率,避免常见设计风险。

weixin_26757925的博客 294

DirectX9中Pixel Coordinates System的一个怪异特性

http://drilian.com/2008/11/25/understanding-half-pixel-and-half-texel-offsets/ 这个文章解释的很详细,他的blog里面也有很多的文章,值得一看哦~. 总结下来就是这样: 在DirectX9中, NDC的坐标系的范围是从左往右x: (-1.0f, 1.0f),  从屏幕上方到下方y: (1.0f, -

?! 676

Multisim14.3中FPGA接口电路设计:原理图项目应用

深入讲解在multisim14.3环境下构建FPGA接口电路的方法,结合原理图设计与项目实践,展现multisim14.3强大的电路仿真能力,提升数字系统开发效率。

weixin_42578963的博客 1157

Get a specific pixel coordinates where your mouse on (cc)

#include<cv.h> #include<highgui.h> #include<stdio.h> IplImage*src=0; voidon_mouse(intevent,intx,inty,intflags,void*ustc) { ...

weixin_30451709的博客 92

Oracle数据库的内存管理优化技巧

Oracle数据库作为企业级数据库管理系统,广泛应用于各种业务场景。内存管理是Oracle数据库性能优化的关键环节,合理的内存管理可以显著提高数据库的响应速度和吞吐量。本文的目的是深入探讨Oracle数据库内存管理的优化技巧,涵盖了系统全局区(SGA)和程序全局区(PGA)的管理、内存分配算法、内存参数调整等方面。通过详细的讲解和实际案例分析,帮助读者掌握优化Oracle数据库内存使用的方法,提高数据库的性能和稳定性。

2502_91592937的博客 996

同源策略与跨域

前言:最近业务上前端同学多次联系说访问腾讯云cos资源的时候因为跨域的问题访问不到。大致看了下腾讯云关于设置跨域访问的教程,按照前端同学给的域名等选项就给配了,而且测试下来也是好的。但是呢一直不知道什么是跨域这里就做一个简单的学习记录。 一、同源策略 同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全功能。同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。...

mijichui2153的博客 1万+

点云数据标注项目 - 世界坐标系(World Coordinates)转换为相机坐标系(Camera Coordinates)和像素坐标系(Pixel Coordinates)

一个用于将世界坐标系(World Coordinates)转换为相机坐标系(Camera Coordinates)和像素坐标系(Pixel Coordinates)的工具。它还可以将激光雷达点云投影到相机图像上,用于数据融合或物体标注。

qq_22662019的博客 361

ABAP Cloud 开发教程的文章目录

本教程涵盖 ABAP 云端 Client 处理、多租户架构、ABAP Cloud开发、动态编程优化、SQL语法改进等技术主题。最新版本1.0.0(更新至2025-12-12),包含197篇文章,重点文章包括《ABAP Client Handling与隔离机制》《ABAP Platform 2021泛型编程》《SAP BTP ABAP多租户应用开发》等,为开发者提供从基础到进阶的实战指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1805

Computing the Pixel Coordinates of a 3D Point---计算3D点的像素坐标

1. Perspective Projection 透视投影 2. 计算3D point的2D Coordinates的数学知识 从这个翻译上来看的话,

HeavenerWen的博客 429

ABAP 7.40 新语法介绍系列之二 - ABAP 类型转换操作符 CONV

这个lv_input_s变量的唯一使命,就是接收来自 char10 类型的 lv_input_c 变量的值,然后传递到 print 方法里去。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1418

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Wegent权限与协作模型详解:团队、项目与实体权限如何设计

Wegent 是一个开源、可自托管的 AI 工作空间,支持编码、协作与自动化。本文详解 Wegent 的**权限与协作模型**:团队(Team)、项目(Project)与实体权限(Entity Permission)三层机制是如何设计的,以及 6 级角色体系、审批流与权限继承在源码中如何落地,帮助你快速理解 Wegent 的协作权限边界。 ## 1. Wegent 权限系统的三大核心概念 We

gitblog_00011的博客 336

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Capstan-Drive 搭建指南:如何用 3D 打印和 ODrive S1 做出 120° 低背隙绳驱执行器测试台

这是一个完全用 PLA 3D 打印的 Capstan Drive 绳驱执行器测试台:它用"滚筒 + 绳索 + 摩擦"替代齿轮箱,以约 241 美元的物料成本实现 8.55:1 准直接驱动减速和 120° 输出旋转。照这份指南走一遍,你会拿到模型文件、买齐 BOM 物料,并从骨架到传动亲手搭出一台可验证的测试台。 ## 原理速览:为什么一根绳子能替代齿轮箱 Capstan Drive 的传动核心

gitblog_00007的博客 390

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Lightweight Charts 插件开发指南:Canvas 位图像素级完美渲染(Pixel Perfect Rendering)最佳实践

在 TradingView Lightweight Charts 中开发 Custom Series 与 Drawing Primitive 插件时,最影响视觉质量的细节之一就是线条、柱体与矩形在屏幕上是否**锐利无模糊**。本指南以官方文档 [Pixel Perfect Rendering](https://link.gitcode.com/i/866385e0b37c942bb8d43759e

gitblog_00509的博客 457

pixel_link记录

export PYTHONPATH=/path2to/pixel_link/pylib/src:$PYTHONPATH https://blog.youkuaiyun.com/northeastsqure/article/details/83655200 https://blog.youkuaiyun.com/u011440558/article/details/78606662 报错: All...

u012135425的博客 409

How To Get Customer's Screen Pixel.

1. Page_Init -> Page_Load -> Page_Render -> Javascript code running...2. Take a example for reference, to avoid refreshing each access, you may keep them in Session or Cookies... /// &...

weixin_30731305的博客 84

DyberPet 桌宠:5分钟搭好第一只桌面虚拟伙伴的完整入门指南

DyberPet 是一个基于 PySide6 的开源桌面宠物框架,它能把可定制的角色放进你的桌面,提供养成、互动、物品商店和番茄钟等能力。想给桌面找个陪伴的普通用户可以直接下载运行;想画自己的角色、写 JSON 做 MOD 的创作者,也有一套现成的素材开发流程。 ## 🖥️ 住进桌面的角色:DyberPet 是什么 先说清楚它和"桌面 GIF"的区别:DyberPet 是一套完整的桌宠 Ap

gitblog_00022的博客 408

dsh-purge:DeepSeek Harness 宿主清洗插件,从安装到生效验证的最短路径

dsh-purge 是装在本机官方 DeepSeek Harness(DSH)上的清洗与提示词注入插件。安装并应用后,宿主侧拦截不再混进回答,「模型答不答」只反映模型本身;卸载时按备份逐个还原,宿主回到原样。 ## 谁该装 dsh-purge:影响范围只限本机官方宿主 用本机官方 DSH 才装得着;第三方托管或社区桌面端没有意义。影响范围与前提: - 只作用于本机已安装的官方 `@deeps

gitblog_00663的博客 466

gemma-4-E2B-it-MLX-6bit解码config.json:混合注意力与8-bit混合精度架构一文读懂

gemma-4-E2B-it-MLX-6bit 是 Google Gemma 4 E2B 指令版模型的 MLX 6-bit 量化版,专为 Apple Silicon 优化,支持文本、图像与音频多模态输入。本文将带你逐段解读 [config.json](https://link.gitcode.com/i/b69749c221ce88d766ebc41a124dc7a0),快速看懂它的混合注意力(s

gitblog_00035的博客 175

拥王者同伴法术伤害增强指南:配置法术专攻与强效链

本仓库是《开拓者:拥王者》与《正义之怒》的剧情队友Build收集,完整加点见[拥王者队友BD.md](https://link.gitcode.com/i/befee634024050c8fd85db9537385978)。想让施法系队友在不换职业的前提下提升法术伤害,可以按“法术专攻 + 超魔(强效)”的顺序做叠加:平值加成先吃满、再让超魔放大,同一道法术的平均伤害能提升八成左右。 ## 适用

gitblog_00553的博客 438

医学图像处理笔记(1)

Introduction 主讲: Lixu Gu 参考书: Digital Image Processing, Kenneth R. Castleman Morphological Image Analysis, Pierre Soille Computer and Robot Vision, R.M.Haralick & L.G. Shapiro

Less is More 846

Lightweight Charts 蜡烛图宽度计算:pixel-perfect-rendering 中 candlestickWidth 与 optimalCandlestickWidth 深入解析

本篇技术指南围绕 Lightweight Charts 官方「Pixel Perfect Rendering」文档中关于 K 线(Candlestick)实体宽度的计算方案展开,完整讲解 `optimalCandlestickWidth` 与 `candlestickWidth` 两个核心函数的算法逻辑、特殊区间处理、奇偶性对齐原理,并结合库内真实渲染源码与官方插件(box-whisker 系列、

gitblog_00947的博客 400
上一篇: C# IEnumerator/IEnumerable
下一篇: 【Unity】Camera.WorldToViewportPoint 计算原理及实现
linuxheik
博客等级 码龄15年 865粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值