Games101学习 - 光栅化

news2024/11/13 9:29:12

Games101中讲解的光栅化的基础知识,本文就来梳理一下。

在UE中使用UTexture2D可以逐像素绘制纹理:
https://blog.csdn.net/grayrail/article/details/142165442

1.绘制三角形

这里可以通过101中讲解的叉积法逐像素绘制三角形:
在这里插入图片描述
绘制效果:
在这里插入图片描述
代码如下:

UTexture2D* UMyBlueprintFunctionLibrary::GenTexture(int32 Width, int32 Height)
{
    // 创建临时纹理
    UTexture2D* NewTexture = UTexture2D::CreateTransient(Width, Height);

    // 配置纹理
    NewTexture->MipGenSettings = TMGS_NoMipmaps;
    NewTexture->CompressionSettings = TC_VectorDisplacementmap;
    NewTexture->SRGB = false;

    // 锁定纹理数据进行写入
    FTexture2DMipMap& Mip = NewTexture->PlatformData->Mips[0];
    void* TextureData = Mip.BulkData.Lock(LOCK_READ_WRITE);

    // 设置默认颜色为黑色
    FColor* FormattedImageData = static_cast<FColor*>(TextureData);
    for (int32 y = 0; y < Height; ++y)
    {
        for (int32 x = 0; x < Width; ++x)
        {
            FormattedImageData[y * Width + x] = FColor::Black; // 背景颜色设置为黑色
        }
    }

    // 定义三角形顶点(A, B, C)
    FVector2D A(Width / 2, Height / 4);  // 三角形顶点A
    FVector2D B(Width / 4, 3 * Height / 4); // 三角形顶点B
    FVector2D C(3 * Width / 4, 3 * Height / 4); // 三角形顶点C

    // 深红色
    FColor TriangleColor = FColor(139, 0, 0, 255);

    // 叉乘判断点P是否在三角形ABC内
    auto IsPointInTriangle = [](const FVector2D& P, const FVector2D& A, const FVector2D& B, const FVector2D& C) -> bool
        {
            FVector2D AP = P - A;
            FVector2D BP = P - B;
            FVector2D CP = P - C;

            FVector2D AB = B - A;
            FVector2D BC = C - B;
            FVector2D CA = A - C;

            // 叉乘结果
            float Cross1 = AB.X * AP.Y - AB.Y * AP.X; // AB 和 AP 的叉乘
            float Cross2 = BC.X * BP.Y - BC.Y * BP.X; // BC 和 BP 的叉乘
            float Cross3 = CA.X * CP.Y - CA.Y * CP.X; // CA 和 CP 的叉乘

            // 如果三个叉乘结果符号相同,则点在三角形内
            return (Cross1 >= 0 && Cross2 >= 0 && Cross3 >= 0) || (Cross1 <= 0 && Cross2 <= 0 && Cross3 <= 0);
        };

    // 超采样抗锯齿:每个像素划分为2x2子像素
    int32 SubPixelCount = 4; // 超采样为2x2子像素
    float InvSubPixelCount = 1.0f / SubPixelCount;

    // 遍历每个像素并应用抗锯齿逻辑
    for (int32 y = 0; y < Height; ++y)
    {
        for (int32 x = 0; x < Width; ++x)
        {
            int32 CoveredSubPixels = 0;

            // 遍历2x2子像素
            for (int32 subY = 0; subY < 2; ++subY)
            {
                for (int32 subX = 0; subX < 2; ++subX)
                {
                    FVector2D SubPixelPos = FVector2D(x + subX / 2, y + (subY + 0.5f) * 0.5f); // 子像素位置
                    if (IsPointInTriangle(SubPixelPos, A, B, C))
                    {
                        CoveredSubPixels++;
                    }
                }
            }

            // 计算覆盖率并设置像素颜色
            float Coverage = CoveredSubPixels * InvSubPixelCount; // 覆盖率(0 到 1)
            if (Coverage > 0)
            {
                // 根据覆盖率设置颜色,颜色的Alpha通道根据Coverage调整
                FColor FinalColor = TriangleColor;
                FinalColor.A = FMath::RoundToInt(255 * Coverage); // 根据覆盖率设置透明度
                FormattedImageData[y * Width + x] = FinalColor;
            }
        }
    }

    // 解锁纹理数据
    Mip.BulkData.Unlock();
    NewTexture->UpdateResource();

    return NewTexture;
}

注意:如需了解具体的头文件、Build.cs引用等请看上一篇:https://blog.csdn.net/grayrail/article/details/142165442

2.抗锯齿

绘制好的三角形放大看会有锯齿:
在这里插入图片描述
Games101中提到了SSAA(超分辨率抗锯齿/反走样)的方法,来消除锯齿:

在这里插入图片描述
大致思路是将一个像素点划分为多个子像素,例如1个像素点细分为4个子像素,然后做叉积包含判断,如果4个像素点有1个包含,覆盖率结果就是0.25,有2个包含结果就是0.5,根据覆盖率的百分比作为插值系数进行绘制,从而得到更好的效果。

UE中绘制效果:
在这里插入图片描述
代码如下:

UTexture2D* UMyBlueprintFunctionLibrary::GenTexture(int32 Width, int32 Height)
{
    // 创建临时纹理
    UTexture2D* NewTexture = UTexture2D::CreateTransient(Width, Height);

    // 配置纹理
    NewTexture->MipGenSettings = TMGS_NoMipmaps;
    NewTexture->CompressionSettings = TC_VectorDisplacementmap;
    NewTexture->SRGB = false;

    // 锁定纹理数据进行写入
    FTexture2DMipMap& Mip = NewTexture->PlatformData->Mips[0];
    void* TextureData = Mip.BulkData.Lock(LOCK_READ_WRITE);

    // 设置默认颜色为黑色
    FColor* FormattedImageData = static_cast<FColor*>(TextureData);
    for (int32 y = 0; y < Height; ++y)
    {
        for (int32 x = 0; x < Width; ++x)
        {
            FormattedImageData[y * Width + x] = FColor::Black; // 背景颜色设置为黑色
        }
    }

    // 定义三角形顶点(A, B, C)
    FVector2D A(Width / 2, Height / 4);  // 三角形顶点A
    FVector2D B(Width / 4, 3 * Height / 4); // 三角形顶点B
    FVector2D C(3 * Width / 4, 3 * Height / 4); // 三角形顶点C

    // 深红色
    FColor TriangleColor = FColor(139, 0, 0, 255);

    // 叉乘判断点P是否在三角形ABC内
    auto IsPointInTriangle = [](const FVector2D& P, const FVector2D& A, const FVector2D& B, const FVector2D& C) -> bool
        {
            FVector2D AP = P - A;
            FVector2D BP = P - B;
            FVector2D CP = P - C;

            FVector2D AB = B - A;
            FVector2D BC = C - B;
            FVector2D CA = A - C;

            // 叉乘结果
            float Cross1 = AB.X * AP.Y - AB.Y * AP.X; // AB 和 AP 的叉乘
            float Cross2 = BC.X * BP.Y - BC.Y * BP.X; // BC 和 BP 的叉乘
            float Cross3 = CA.X * CP.Y - CA.Y * CP.X; // CA 和 CP 的叉乘

            // 如果三个叉乘结果符号相同,则点在三角形内
            return (Cross1 >= 0 && Cross2 >= 0 && Cross3 >= 0) || (Cross1 <= 0 && Cross2 <= 0 && Cross3 <= 0);
        };

    int SubPixelCount = 8;

    // 超采样抗锯齿:子像素划分
    float SubPixelStep = 1.0f / SubPixelCount; // 子像素的步长
    int32 TotalSubPixels = SubPixelCount * SubPixelCount; // 子像素的总数

    // 遍历每个像素并应用抗锯齿逻辑
    for (int32 y = 0; y < Height; ++y)
    {
        for (int32 x = 0; x < Width; ++x)
        {
            int32 CoveredSubPixels = 0;

            // 遍历 SubPixelCount x SubPixelCount 子像素
            for (int32 subY = 0; subY < SubPixelCount; ++subY)
            {
                for (int32 subX = 0; subX < SubPixelCount; ++subX)
                {
                    FVector2D SubPixelPos = FVector2D(x + (subX + 0.5f) * SubPixelStep, y + (subY + 0.5f) * SubPixelStep); // 子像素位置
                    if (IsPointInTriangle(SubPixelPos, A, B, C))
                    {
                        CoveredSubPixels++;
                    }
                }
            }

            // 计算覆盖率并设置像素颜色
            float Coverage = static_cast<float>(CoveredSubPixels) / TotalSubPixels; // 覆盖率(0 到 1)
            if (Coverage > 0)
            {
                FColor FinalColor = TriangleColor;
                FinalColor.R = FMath::RoundToInt(255 * Coverage);
                FormattedImageData[y * Width + x] = FinalColor;
            }
        }
    }

    // 解锁纹理数据
    Mip.BulkData.Unlock();
    NewTexture->UpdateResource();

    return NewTexture;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2131742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4G物联网智能电表是什么?什么叫4G物联网智能电表?

4G物联网智能电表是一种结合了4G无线通信技术的新型电能计量设备&#xff0c;用于实时采集和传输用户的用电数据。它通过集成现代信息技术和电力电子技术&#xff0c;不仅能够精确测量电力消耗&#xff0c;还能实现远程数据传输、数据分析、远程控制等多种功能。本文将详细介绍…

【鸿蒙】HarmonyOS NEXT星河入门到实战6-组件化开发-样式结构重用常见组件

目录 1、Swiper轮播组件 1.1 Swiper基本用法 1.2 Swiper的常见属性 1.3 Swiper的样式自定义 1.3.1 基本语法 1.3.2 案例小米有品 2、样式&结构重用 2.1 Extend:扩展组件(样式、事件) 2.2 Styles:抽取通用属性、事件 2.3 Builder:自定义构建函数(结构、样式、事…

宝马销量崩了,自己作死拦都拦不住

文 | AUTO芯球 作者 | 雷慢 什么叫有人欢喜有人忧&#xff1f;这就是啦&#xff1a; 问界M9五座版上市当天&#xff0c;宣布M9大定破了13万台&#xff0c; 另一边呢&#xff0c;宝马股票当天暴跌近10%&#xff0c; 原因是什么呢&#xff0c;是宝马的业绩预期降了&#xff0…

把公文写得好准快,原来他们悄悄使用了这款工具……

在公文写作时&#xff0c;您可能面临着以下挑战&#xff1a; 1、材料要求高&#xff0c;需要全面掌握思想站位、时效性、文风表达、内容法定性、行为规范性、表达特定性。 2、要求理论功底强、精通专业知识、遣词造句精准、强抗压以及百科知识储备丰富。 3、老题新作构思难&…

Spire.PDF for .NET【页面设置】演示:为 PDF 添加背景颜色或背景图像

在 PDF 文档中&#xff0c;背景是指页面内容背后的整体视觉外观。背景可以是简单的纯色&#xff0c;也可以是您选择的图像。向 PDF 添加背景可以帮助您增加文档的视觉趣味&#xff0c;并提高可读性。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET以编程方式设置 PDF…

固态继电器(SSR):分步概述

固态继电器(SSR)已成为现代电气和电子控制系统中的重要组成部分。它们通过提供更快的切换速度、更长的使用寿命和更好的可靠性&#xff0c;为传统机电继电器(EMR)提供了更好的替代方案。本文将逐步探讨SSR的工作原理、主要特性、优势和实际应用。 什么是固态继电器&#xff1f;…

稳石机器人第四季度全员冲刺大会圆满落幕

2024年已在挑战与机遇的交织中悄然流逝了八个月&#xff0c;在正式入秋之际&#xff0c;稳石机器人在深圳总部一楼召开了第四季度全员大会。本次大会以“携手共进&#xff0c;共创未来”为主题&#xff0c;旨在总结过去&#xff0c;规划未来&#xff0c;并激发团队为实现公司目…

旅游网站设计与实现:SpringBoot技术手册

第三章 系统分析 开发一个系统首先要对系统进行分析&#xff0c;是开发者针对系统实际客户对软件应用的一个调查访问和研究&#xff0c;弄清用户对软件需求的具体要求&#xff0c;同时开发者还要对系统开发的经济和可技术上是否可行进行分析&#xff0c;并确定系统开发的成本和…

一文读懂:如何将广告融入大型语言模型(LLM)输出

本文是我翻译过来的&#xff0c;讨论了在线广告行业的现状以及如何将大型语言模型&#xff08;LLM&#xff09;应用于在线广告。 原文请参见”阅读原文“。 在2024年&#xff0c;预计全球媒体广告支出的69%将流向数字广告市场。这个数字预计到2029年将增长到79%。在Meta的2024…

【Docker部署ELK】(7.15)

1、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.0 docker pull docker.elastic.co/kibana/kibana:7.15.0 docker pull docker.elastic.co/logstash/logstash:7.15.02、配置文件&#xff08;解压资源到D盘DOCKER目录下&#xff09; 2.1 配置文件…

工作日常(一) - Shell和Linux命令(1)文件类

一、文件类 1. ls | 列出文件和目录 2. cd | 切换目录 3. mkdir | 创建目录 4. rmdir | 删除空目录 5. du -sh * | 查看当前目录下各个文件的文件大小 6. wc -l 文件名 | 统计指定文件的内容行数 7. touch 文件名 | 创建文件 8. rm 文件名 | 删除文件 9. cp | 复制文件 10. m…

Jwt、Filter、Interceptor

目录 JWT(Json Web Token) jwt令牌 组成 应用场景 生成令牌 解析令牌 登录实例 Filter过滤器 Filter Filter登录校验 Interceptor拦截器 Interceptor 拦截路径 执行流程 登录实例 JWT(Json Web Token) jwt令牌 定义了一种简洁的、自包含的格式&#xff0c;…

Numpy版本过高问题的解决办法

1、问题的产生 在运行一个魔塔大模型程序的时候&#xff0c;提示Numpy的版本过高&#xff0c;如下图&#xff1a; 2、查看当前的Numpy版本 利用pip show numpy查看Numpy的版本号&#xff1a; pip show numpy 3、卸载numpy pip uninstall numpy 4、安装1.24.3版本的numpy pi…

掌握ChatGPT:高效利用AI助手

2023 年 3 月 15 日&#xff0c;ChatGPT-4 的诞生标志着人类进入了一个全新的 人机协作时代。这个时代就像一个混沌初开的新世界&#xff0c;而 ChatGPT 则是这个新世界里诞生的一个新物种。 这个新物种的心智如同一个四五岁的小孩&#xff0c;在与它频繁互动中&#xff0c;人…

C++ 左值与右值浅谈

左值与右值 序言概念左值和右值的划分理解右值引用常量左值引用与右值引用 移动语义引用折叠完美转发 参考资料 序言 虽然平常都算是了解左值&#xff0c;右值的用法&#xff0c;但是好记性不如烂笔头&#xff0c;记下来供大家评鉴&#xff0c;有错改错&#xff0c;有善赞善&a…

Jmeter接口测试之常用断言

在接口测试中&#xff0c;我们需要检查请求处理结果是否正确。当请求的响应状态码为200&#xff0c;是否表时接口功能正常呢&#xff1f;显然是不正确的。 响应状态为200&#xff0c;只能表明服务处理了你的请求&#xff0c;同时进行了结果返回&#xff1b;但并不能代表处理的…

机器学习--卷积神经网络(包括python实现)

卷积神经网络 1. 计算方法 &#xff08;1&#xff09;输入和输出channel 1时 首先我们要知道channel是什么意思&#xff0c;顾名思义channel就是“通道”的意思qwq。我们来举个例子&#xff0c;在计算机视觉中&#xff0c;如果一张图片是黑白的&#xff0c;那么每个像素点都…

微信小程序页面制作——婚礼邀请函(含代码)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

windows下ardusub仿真

接上篇&#xff1a;windows编译ardupilot源码教程 执行以下命令。 #在ardusub根目录下执行下面命令 cd ./Tools/autotest./waf configure --debugpython sim_vehicle.py -v ArduCopter -f quad --console --map -D -L RATBeach 编译时间较长&#xff0c;之后会打开三个窗口。 …