D3Dshader,像素着色器实现多种形状放大镜(圆形、方形、三角形、梯形、六边形、心形、五角星形)

本文主要是介绍D3Dshader,像素着色器实现多种形状放大镜(圆形、方形、三角形、梯形、六边形、心形、五角星形),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、圆形放大镜
  • 三、矩形放大镜
  • 四、三角形放大镜
  • 五、梯形放大镜
  • 六、六边形放大镜
  • 七、心形放大镜
  • 八、五角星形放大镜
  • 总结


前言

之前实现了一系列不同形状的放大镜,参考了网上很多文章以及资料,完成后发上来分享一下。


提示:以下是本篇文章正文内容,下面案例可供参考

一、圆形放大镜

作为最基础的放大镜样式,实现起来也比较简单,在指定圆形区域的纹理乘以一个放大系数(小于零),直接上代码,在代码里注释。

    //int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小float dist = distance(tex, center);//当前纹理点与放大镜中心的距离//圆内if (dist < radius)//当前纹理点在放大镜中时{       tex -= center;//将纹理坐标轴移动到以放大镜中心为原心的纹理坐标空间tex = tex * Times;//放大,即让当前纹理显示更靠进圆心的纹理区域tex += center;//恢复成原来的纹理坐标空间}float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出

效果:在这里插入图片描述

三、矩形放大镜

根据圆心以及半径划定一个矩形区域
关键区域的代码如下:

	//int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小//当前纹理在矩形区域内,矩形边长为radius if ((tex.x < center.x + radius / 2) && (tex.x > center.x - radius / 2) && (tex.y < center.y + radius / 2) && (tex.y > center.y - radius / 2)){tex -= center;tex = tex * Times;tex += center;            }float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出   

效果如下:
在这里插入图片描述

四、三角形放大镜

关键区域的代码如下:

	    //int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小float g = sin(PI/3)*2;center.y += (g / 4) * radius;tex -= center;//a、b、c为三角形的三个顶点float2 a = float2(-radius / 2, 0);float2 b = float2(0, -radius * g/2);float2 c = float2(radius / 2, 0);if (inTriangle(a, b, c, tex))//tex是否在abc构成的三角形内{tex = tex * Times;}tex += center;float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出

inTriangle函数用以判断当前点tex是否在abc三点构成的三角形内,也就是说可以通过更改abc三个点的位置来更改三角形的形状,后续的五角星放大镜也用到了这个函数。其中用到了伪叉积的概念,伪叉积就不展开说了,可以百度,inTriangle函数如下所示:
参考文章链接:链接

bool inTriangle(float2 a, float2 b, float2 c, float2 tex)
{float2 AB = float2(b - a);float2 BC = float2(c - b);float2 CA = float2(a - c);float2 AP = float2(tex - a);float2 BP = float2(tex - b);float2 CP = float2(tex - c);bool Out_In1 = AB.x * AP.y - AB.y * AP.x > 0&& BC.x * BP.y - BC.y * BP.x > 0&& CA.x * CP.y - CA.y * CP.x > 0;bool Out_In2 = AB.x * AP.y - AB.y * AP.x < 0&& BC.x * BP.y - BC.y * BP.x < 0&& CA.x * CP.y - CA.y * CP.x < 0;return Out_In1 || Out_In2;}

三角形马赛克效果如下:
在这里插入图片描述

五、梯形放大镜

跟之前的操作类似,求出梯形的区域,在区域内的纹理进行放大操作。

	    //int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小//以梯形底边中心为原点,求出另外两条直线的公式float a = 1.732; //根号三  另外两条边的公式 1:y=-ax-(a/2)*R  2: y=ax-(a/2)*R center.y += (a / 4) * radius;if (tex.y < center.y && tex.y > center.y - (a / 2) * radius)//将范围限定在梯形上下两边中{tex -= center;//梯形内if ((tex.y > (-1 * a * tex.x - a * radius)) && (tex.y > ( a * tex.x - a * radius))){tex = tex * Times;}}tex += center;float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出

在这里插入图片描述

六、六边形放大镜

六边形区域可由上下两边+剩下四个斜边构成:

        //int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小//以六边形中点为原点,求出另外四条直线的公式//1.732=根号三  另外四条边的公式 1:y=-ax-a*R  2: y=ax-2*R 3:y=a*x+a*R ,4:y=-a*x+a*Rfloat a = sin(PI/3)*2;if ((tex.y < center.y + radius / 2) && (tex.y > center.y - radius / 2))//将范围限定上下{    tex -= center;radius *=0.6;if ((tex.y > (-1. * a * tex.x - a * radius)) && (tex.y > (a * tex.x - a * radius)) && (tex.y < (a * tex.x + a * radius)) && (tex.y < (-1.*a * tex.x + a * radius))){tex = tex * Times;         }tex += center;  }float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出

在这里插入图片描述
当然,也可以按照之前画三角形的方法实现,六边形就是由六个三角形构成的。

七、心形放大镜

心形放大镜的核心在于构建出一个心形区域。

         //int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小//爱心公式((x*x+y*y-1)^3)=x^2*y^3tex -= center; //以中心为原点        if (inHeart(tex,  radius) != 0){tex *= Times;} tex += center;float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize);
float inHeart(float2 tex, float size)//用于判断当前点是否在心性内部
{if (size == 0.){return 0;}tex /= size;float s = tex.x * tex.x - tex.y * -tex.y - 1;//爱心公式((x*x+y*y-1)^3)=x^2*y^3float f1 = s * s * s;float f2 = tex.x * tex.x * tex.y * tex.y * tex.y * -1;return step(f1, f2);}

效果:
在这里插入图片描述

八、五角星形放大镜

五角星是由十个三角形构成的,首先求出这十个三角形的各点的坐标,再判断当前点是否在这十个三角形内。
参考的文章:链接
代码:

   		//int magnifying_Center_x; //镜头中心x坐标(-100到100)//int magnifying_Center_y; //镜头中心y坐标(-100到100)//int magnifying_Radius; //(0到100)放大镜半径    //int magnifyingl_Times; //(0到10)放大倍率//v2TexSize为窗口大小 例如(1920,1080)float2 center = float2(0.5 + magnifying_Center_x / 200, 0.5-magnifying_Center_y / 200) * v2TexSize;//计算出放大镜中心点float radius = magnifying_Radius / 100 * v2TexSize.y;//一般情况下窗口都是呈现长方形的,选取短边作为半径扩展系数float Times = (1 - magnifyingl_Times / 10);//计算出放大的倍率,Times 越小,放大程度越大tex *= v2TexSize;//将范围(0-1)的纹理恢复至窗口大小float R = radius;//外五角半径float r = radius * sin(PI/10.) / cos(PI/5.);//内五角半径float2 PointO[5];//外五角float2 PointI[5];//内五角tex -= center;        for (int i = 0; i < 5; i++){PointO[i] = float2(R * cos(0.5 * PI + i * 0.4 * PI), -R * sin(0.5 * PI + i * 0.4 * PI));PointI[i] = float2(r * cos(0.7 * PI + i * 0.4 * PI), -r * sin(0.7 * PI + i * 0.4 * PI));if (inTriangle(float2(0, 0), PointO[i], PointI[i], tex)){tex *= Times;}}if (inTriangle(float2(0, 0), PointO[0], PointI[4], tex)){tex *= Times;}for (int j = 1;j < 5; j++){if (inTriangle(float2(0, 0), PointO[j], PointI[j-1], tex)){tex *= Times;}}tex += center;float4 outp = g_Tex.Sample(g_SamLinear, tex / v2TexSize); //拿到当前放大镜处理后的纹理        return outp;//输出

效果:
在这里插入图片描述

总结

分享了使用HLSL实现七种不同形状放大镜的实现方法,其中有些方法肯定存在不足之处,欢迎指出,谢谢。

这篇关于D3Dshader,像素着色器实现多种形状放大镜(圆形、方形、三角形、梯形、六边形、心形、五角星形)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/167622

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现