当前位置:网站首页>Opengl/webgl shader development getting started guide
Opengl/webgl shader development getting started guide
2022-07-08 02:15:00 【Brain in new VAT】
Learning to write graphics shaders is learning to use GPU The power of , Its thousands of cores all run in parallel . This is a kind of programming that requires different ways of thinking , But its huge potential is worth the initial investment .
Almost every modern graphic simulation you see is done in some way GPU Written code provides support , From the tip AAA Realistic lighting effect in the game to 2D Post treatment effect and fluid simulation .
Minecraft A scene in , Before and after applying some shaders .
1、 The purpose of this guide
Shader programming sometimes becomes a mysterious dark magic , And often misunderstood . There are many code examples that show you how to create incredible effects , But little or no explanation was provided . This guide aims to bridge this gap . I will pay more attention to the basics of writing and understanding shader code , So you can easily adjust 、 Compose or write your own code from scratch !
This is a general guide , So what you learn here will apply to anything that can run shaders .
2、 What is a shader ?
Shaders are just programs that run in the graphics pipeline and tell the computer how to render each pixel . These programs are called shaders , Because they are usually used to control lighting and shadows effect , But there is no reason why they cannot deal with other special effects .
Shaders are written in a special shading language . Never mind , You don't have to go out and learn a new language ; We will use GLSL(OpenGL Coloring language ), It's kind of like C Language . There are many coloring languages for different platforms , But because they are applicable in GPU Up operation , So they are very similar .
Be careful : This article focuses on fragment shaders . If you are curious about other types of shaders , Can be in OpenGL Wiki Read about the phases in the graphics pipeline on .
3、 Let's get started !
We will use... In this tutorial ShaderToy. This allows you to start programming the colorator directly in the browser , Without any setup !ShaderToy Use WebGL Rendering , So you need a browser that can support this function . Creating an account is optional , But it's very convenient for saving code .
Be careful : At the time of writing ,ShaderToy In the testing phase . Some small ones UI/ Grammatical details may vary slightly .
single click New Shader after , You should see the following :
If you are not logged in , Your interface may be slightly different .
The small black arrow at the bottom is where you click to compile the code .
4、 What happened? ?
I will explain how shaders work in one sentence . are you ready ? Start !
The only purpose of the shader is to return four numbers :r、g、b and a.
This is what it has done or can do . The function you see in front of you runs for each pixel on the screen . It returns these four color values , This becomes the color of the pixel . This is the so-called pixel shader ( Sometimes called Fragment Shader ).
Consider this , Let's try to turn the screen into pure red .rgba( Red 、 green 、 Blue and “alpha”, Define transparency ) Value from 0 To 1, So what we need to do is return r,g,b,a = 1,0,0,1
.ShaderToy Expect the final pixel color to be stored in fragColor.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
fragColor = vec4(1.0,0.0,0.0,1.0);
}
Congratulations ! This is your first working shader !
Challenge : Can you change it to pure gray ?
vec4 Just a data type , So we can declare colors as variables , As shown below :
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec4 solidRed = vec4(1.0,0.0,0.0,1.0);
fragColor = solidRed;
}
however , This is not very exciting . We have the ability to run code in parallel on hundreds of thousands of pixels , And we set them all to the same color .
Let's try to render a gradient on the screen . ok , If you don't know something about the pixels we are affecting , For example, its position on the screen , There is nothing we can do …
5、 Shader input
Pixel shaders pass some variables For your use . The most useful thing for us is fragCoord, It saves pixels x and y( as well as z, If you are in the 3D Work in China ) coordinate . Let's try to turn all pixels on the left half of the screen black , Turn all pixels on the right half red :
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0);//This is actually black right now
if(xy.x > 300.0){//Arbitrary number, we don't know how big our screen is!
solidRed.r = 1.0;//Set its red component to 1.0
}
fragColor = solidRed;
}
Be careful : For any , You can go through 、 And or through obj.x、obj.y、obj.z、obj.w or obj.r 、obj.g 、obj.b 、obj.a visit vec4 Its components . They are equivalent ; This is just a convenient way of naming , To make your code more readable , So that others can see obj.r when , They will understand obj Represents a color .
Do you see the problem in the code above ? Try clicking the full screen button in the lower right corner of the preview window .
The ratio of the red screen will vary according to the size of the screen . To make sure half of the screen is red , We need to know how big the screen is . Screen size is not a built-in variable like pixel position , Because it is usually set up by the programmer who builds the application . under these circumstances , Setting the screen size is ShaderToy Developer .
If something is not a built-in variable , You can transfer this information from CPU( Your main program ) Send to GPU( Your shader ).ShaderToy Dealt with this problem for us . You can Shader Inputs Tab to see all the variables passed to the shader . In this way from CPU Pass on to GPU The variables in the GLSL called Uniform.
Let's adjust the code above to get the center of the screen correctly . We need to use shader input iResolution:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size
xy.y = xy.y / iResolution.y;
// Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now
if(xy.x > 0.5){
solidRed.r = 1.0; //Set its red component to 1.0
}
fragColor = solidRed;
}
If you try to enlarge the preview window this time , The color should still perfectly divide the screen in two .
6、 From split to gradient
It should be easy to turn it into a gradient . Our color values range from 0 To 1, Coordinates are also from 0 To 1.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size
xy.y = xy.y / iResolution.y;
// Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now
solidRed.r = xy.x; //Set its red component to the normalized x value
fragColor = solidRed;
}
look !
Challenge : Can you turn it into a vertical gradient ? The diagonal ? Gradient with multiple colors ?
If you play enough , You can see that there are coordinates in the upper left corner (0,1), instead of (0,0). It's important to remember that .
7、 The plot
It's fun to play with colors , But if we want to do something impressive , Our shader must be able to take input from the image and change it . In this way , We can make a shader that affects the whole game screen ( For example, underwater fluid effect or color correction ), Or only some objects are affected in some way according to the input ( For example, realistic lighting system ).
If we program on a common platform , You need to put the image ( Or texture ) As Uniform Send to GPU, Just like sending screen resolution .ShaderToy Solved this problem for us . There are four input channels at the bottom :
ShaderToy Four input channels of
single click iChannel0 And choose any texture you like ( Images ).
After completion , You now have an image being passed to the shader . however , There is a question : No, DrawImage() function . please remember , The only thing a pixel shader can do is change the color of each pixel .
So if we can only return one color , How do we paint textures on the screen ? We need to map the current pixel of the shader to the corresponding pixel on the texture in some way :
according to (0,0) Position on the screen , You may need to flip y Axis to map the texture correctly . At the time of writing ,ShaderToy Updated , Its origin is at the upper left , So there is no need to flip anything .
We can do that by using texture(textureData,coordinates) Function to do this , This function combines texture data with (x, y) Coordinate pairs as input , And take the texture color at these coordinates as a return vec4.
You can match the coordinates to the screen in any way you like . You can paint the entire texture on a quarter of the screen ( By skipping pixels , Effectively shrink it ) Or paint only part of the texture .
Because we just want to view the image , So we will match pixels 1:1:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy / iResolution.xy;//Condensing this into one line
vec4 texColor = texture(iChannel0,xy);//Get the pixel at xy from iChannel0
fragColor = texColor;//Set the screen pixel to that color
}
such , We have the first picture !
Now we have extracted data from texture correctly , You can operate it at will ! You can stretch it and scale it , Or play with its color .
Let's try to modify it with a gradient , Similar to what we did above :
texColor.b = xy.x;
Congratulations , You just made your first post-processing effect !
Challenge : Can you write a shader that turns an image into black and white ?
Please note that , Even if it is a still image , What you see in front of you also happens in real time . You can see it for yourself by replacing still images with videos : Click again iChannel0 Enter and select one of the videos .
8、 Add some actions
up to now , All our effects are static . By using ShaderToy Input provided to us , We can do more interesting things .iGlobalTime Is an increasing variable ; We can use it as a seed to make periodic effects . Let's try to play with colors :
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy / iResolution.xy; // Condensing this into one line
vec4 texColor = texture(iChannel0,xy); // Get the pixel at xy from iChannel0
texColor.r *= abs(sin(iGlobalTime));
texColor.g *= abs(cos(iGlobalTime));
texColor.b *= abs(sin(iGlobalTime) * cos(iGlobalTime));
fragColor = texColor; // Set the screen pixel to that color
}
GLSL Sine and cosine functions are built in , And many other useful functions , For example, get the length of a vector or the distance between two vectors . Color should not be negative , So we make sure to use abs Function to get the absolute value .
Challenge : You can make a shader , Change the image back and forth from black and white to full color ?
9、 Conclusion
Although you may be used to stepping through the code and printing out the values of everything to see what happened , But this is impossible when writing shaders . You may find some platform specific debugging tools , But usually the best way is to set the value being tested to the graph you can see .
These are just the basics of using shaders , But familiarity with these basics will enable you to do more . Browse ShaderToy Effect on , See if you can understand or copy some of these effects !
One thing I didn't mention in this tutorial is Vertex Shaders . They are still written in the same language , Except that they run on every vertex instead of every pixel , They return a position and a color . Vertex shaders are usually responsible for putting 3D The scene is projected onto the screen ( Something built into most graphics pipelines ). Pixel shaders are responsible for many of the advanced effects we see , This is why we pay attention .
The final challenge : Can you write a shader to remove ShaderToy The green screen in the previous video , And add another video as the background in the first video ?
Link to the original text : Novice guide to shader development — BimAnt
边栏推荐
- Redisson distributed lock unlocking exception
- VIM string substitution
- Where to think
- 喜欢测特曼的阿洛
- What are the types of system tests? Let me introduce them to you
- The generosity of a pot fish
- leetcode 866. Prime Palindrome | 866. 回文素数
- Nacos microservice gateway component +swagger2 interface generation
- Can you write the software test questions?
- Principle of least square method and matlab code implementation
猜你喜欢
[target tracking] |atom
QT -- create QT program
常见的磁盘格式以及它们之间的区别
软件测试笔试题你会吗?
银行需要搭建智能客服模块的中台能力,驱动全场景智能客服务升级
Ml backward propagation
I don't know. The real interest rate of Huabai installment is so high
The bank needs to build the middle office capability of the intelligent customer service module to drive the upgrade of the whole scene intelligent customer service
[knowledge map] interpretable recommendation based on knowledge map through deep reinforcement learning
力争做到国内赛事应办尽办,国家体育总局明确安全有序恢复线下体育赛事
随机推荐
XMeter Newsletter 2022-06|企业版 v3.2.3 发布,错误日志与测试报告图表优化
Towards an endless language learning framework
谈谈 SAP 系统的权限管控和事务记录功能的实现
burpsuite
Nmap tool introduction and common commands
Semantic segmentation | learning record (2) transpose convolution
Introduction à l'outil nmap et aux commandes communes
Introduction to ADB tools
Redisson distributed lock unlocking exception
MQTT X Newsletter 2022-06 | v1.8.0 发布,新增 MQTT CLI 和 MQTT WebSocket 工具
[knowledge map] interpretable recommendation based on knowledge map through deep reinforcement learning
See how names are added to namespace STD from cmath file
直接加比较合适
Nacos microservice gateway component +swagger2 interface generation
In depth analysis of ArrayList source code, from the most basic capacity expansion principle, to the magic iterator and fast fail mechanism, you have everything you want!!!
Node JS maintains a long connection
Reading notes of Clickhouse principle analysis and Application Practice (7)
I don't know. The real interest rate of Huabai installment is so high
Direct addition is more appropriate
Leetcode question brushing record | 485_ Maximum number of consecutive ones