WebGL Shaders and GLSL
文章推薦指數: 80 %
As mentioned in how it works WebGL requires 2 shaders every time you draw something. A vertex shader and a fragment shader. Each shader is a function. English Français 日本語 한국어 Polski Portuguese Русский 简体中文 TableofContents WebGLFundamentals.org Fix,Fork,Contribute WebGLShadersandGLSL ThisisacontinuationfromWebGLFundamentals. Ifyouhaven'treadabouthowWebGLworksyoumightwanttoreadthisfirst. We'vetalkedaboutshadersandGLSLbuthaven'treallygiventhemanyspecificdetails. IthinkIwashopingitwouldbeclearbyexamplebutlet'strytomakeitclearerjustincase. AsmentionedinhowitworksWebGLrequires2shaderseverytimeyou drawsomething.Avertexshaderandafragmentshader.Eachshaderisafunction.Avertex shaderandfragmentshaderarelinkedtogetherintoashaderprogram(orjustprogram).Atypical WebGLappwillhavemanyshaderprograms. VertexShader AVertexShader'sjobistogenerateclipspacecoordinates.Italwaystakestheform voidmain(){ gl_Position=doMathToMakeClipspaceCoordinates } Yourshaderiscalledoncepervertex.Eachtimeit'scalledyouarerequiredtosetthespecialglobalvariable,gl_Positiontosomeclipspacecoordinates. Vertexshadersneeddata.Theycangetthatdatain3ways. Attributes(datapulledfrombuffers) Uniforms(valuesthatstaythesameforallverticesofasingledrawcall) Textures(datafrompixels/texels) Attributes Themostcommonwayisthroughbuffersandattributes. Howitworkscoveredbuffersand attributes.Youcreatebuffers, varbuf=gl.createBuffer(); putdatainthosebuffers gl.bindBuffer(gl.ARRAY_BUFFER,buf); gl.bufferData(gl.ARRAY_BUFFER,someData,gl.STATIC_DRAW); Then,givenashaderprogramyoumadeyoulookupthelocationofitsattributes atinitializationtime varpositionLoc=gl.getAttribLocation(someShaderProgram,"a_position"); andatrendertimetellWebGLhowtopulldataoutofthosebuffersandintotheattribute //turnongettingdataoutofabufferforthisattribute gl.enableVertexAttribArray(positionLoc); varnumComponents=3;//(x,y,z) vartype=gl.FLOAT;//32bitfloatingpointvalues varnormalize=false;//leavethevaluesastheyare varoffset=0;//startatthebeginningofthebuffer varstride=0;//howmanybytestomovetothenextvertex //0=usethecorrectstridefortypeandnumComponents gl.vertexAttribPointer(positionLoc,numComponents,type,normalize,stride,offset); InWebGLfundamentalsweshowedthatwecandonomath intheshaderandjustpassthedatadirectlythrough. attributevec4a_position; voidmain(){ gl_Position=a_position; } Ifweputclipspaceverticesintoourbuffersitwillwork. Attributescanusefloat,vec2,vec3,vec4,mat2,mat3,andmat4astypes. Uniforms Forashaderuniformsarevaluespassedtotheshaderthatstaythesame forallverticesinadrawcall.Asaverysimpleexamplewecouldaddanoffsetto thevertexshaderabove attributevec4a_position; +uniformvec4u_offset; voidmain(){ gl_Position=a_position+u_offset; } Andnowwecouldoffseteveryvertexbyacertainamount.Firstwe'dlookupthe locationoftheuniformatinitializationtime varoffsetLoc=gl.getUniformLocation(someProgram,"u_offset"); Andthenbeforedrawingwe'dsettheuniform gl.uniform4fv(offsetLoc,[1,0,0,0]);//offsetittotherighthalfthescreen Notethatuniformsbelongtoindividualshaderprograms.Ifyouhavemultipleshaderprograms withuniformsofthesamenamebothuniformswillhavetheirownlocationsandholdtheirown values.Whencallinggl.uniform???you'reonlysettingtheuniformforthecurrentprogram. Thecurrentprogramisthelastprogramyoupassedtogl.useProgram. Uniformscanbemanytypes.Foreachtypeyouhavetocallthecorrespondingfunctiontosetit. gl.uniform1f(floatUniformLoc,v);//forfloat gl.uniform1fv(floatUniformLoc,[v]);//forfloatorfloatarray gl.uniform2f(vec2UniformLoc,v0,v1);//forvec2 gl.uniform2fv(vec2UniformLoc,[v0,v1]);//forvec2orvec2array gl.uniform3f(vec3UniformLoc,v0,v1,v2);//forvec3 gl.uniform3fv(vec3UniformLoc,[v0,v1,v2]);//forvec3orvec3array gl.uniform4f(vec4UniformLoc,v0,v1,v2,v4);//forvec4 gl.uniform4fv(vec4UniformLoc,[v0,v1,v2,v4]);//forvec4orvec4array gl.uniformMatrix2fv(mat2UniformLoc,false,[4xelementarray])//format2ormat2array gl.uniformMatrix3fv(mat3UniformLoc,false,[9xelementarray])//format3ormat3array gl.uniformMatrix4fv(mat4UniformLoc,false,[16xelementarray])//format4ormat4array gl.uniform1i(intUniformLoc,v);//forint gl.uniform1iv(intUniformLoc,[v]);//forintorintarray gl.uniform2i(ivec2UniformLoc,v0,v1);//forivec2 gl.uniform2iv(ivec2UniformLoc,[v0,v1]);//forivec2orivec2array gl.uniform3i(ivec3UniformLoc,v0,v1,v2);//forivec3 gl.uniform3iv(ivec3UniformLoc,[v0,v1,v2]);//forivec3orivec3array gl.uniform4i(ivec4UniformLoc,v0,v1,v2,v4);//forivec4 gl.uniform4iv(ivec4UniformLoc,[v0,v1,v2,v4]);//forivec4orivec4array gl.uniform1i(sampler2DUniformLoc,v);//forsampler2D(textures) gl.uniform1iv(sampler2DUniformLoc,[v]);//forsampler2Dorsampler2Darray gl.uniform1i(samplerCubeUniformLoc,v);//forsamplerCube(textures) gl.uniform1iv(samplerCubeUniformLoc,[v]);//forsamplerCubeorsamplerCubearray There'salsotypesbool,bvec2,bvec3,andbvec4.Theyuseeitherthegl.uniform?f?orgl.uniform?i? functions. Notethatforanarrayyoucansetalltheuniformsofthearrayatonce.Forexample //inshader uniformvec2u_someVec2[3]; //inJavaScriptatinittime varsomeVec2Loc=gl.getUniformLocation(someProgram,"u_someVec2"); //atrendertime gl.uniform2fv(someVec2Loc,[1,2,3,4,5,6]);//settheentirearrayofu_someVec2 Butifyouwanttosetindividualelementsofthearrayyoumustlookupthelocationof eachelementindividually. //inJavaScriptatinittime varsomeVec2Element0Loc=gl.getUniformLocation(someProgram,"u_someVec2[0]"); varsomeVec2Element1Loc=gl.getUniformLocation(someProgram,"u_someVec2[1]"); varsomeVec2Element2Loc=gl.getUniformLocation(someProgram,"u_someVec2[2]"); //atrendertime gl.uniform2fv(someVec2Element0Loc,[1,2]);//setelement0 gl.uniform2fv(someVec2Element1Loc,[3,4]);//setelement1 gl.uniform2fv(someVec2Element2Loc,[5,6]);//setelement2 Similarlyifyoucreateastruct structSomeStruct{ boolactive; vec2someVec2; }; uniformSomeStructu_someThing; youhavetolookupeachfieldindividually varsomeThingActiveLoc=gl.getUniformLocation(someProgram,"u_someThing.active"); varsomeThingSomeVec2Loc=gl.getUniformLocation(someProgram,"u_someThing.someVec2"); TexturesinVertexShaders SeeTexturesinFragmentShaders. FragmentShader AFragmentShader'sjobistoprovideacolorforthecurrentpixelbeingrasterized. Italwaystakestheform precisionmediumpfloat; voidmain(){ gl_FragColor=doMathToMakeAColor; } Yourfragmentshaderiscalledonceperpixel.Eachtimeit'scalledyouarerequired tosetthespecialglobalvariable,gl_FragColortosomecolor. Fragmentshadersneeddata.Theycangetdatain3ways Uniforms(valuesthatstaythesameforeverypixelofasingledrawcall) Textures(datafrompixels/texels) Varyings(datapassedfromthevertexshaderandinterpolated) UniformsinFragmentShaders SeeUniformsinShaders. TexturesinFragmentShaders Gettingavaluefromatextureinashaderwecreateasampler2DuniformandusetheGLSL functiontexture2Dtoextractavaluefromit. precisionmediumpfloat; uniformsampler2Du_texture; voidmain(){ vec2texcoord=vec2(0.5,0.5)//getavaluefromthemiddleofthetexture gl_FragColor=texture2D(u_texture,texcoord); } Whatdatacomesoutofthetextureisdependentonmanysettings. Ataminimumweneedtocreateandputdatainthetexture,forexample vartex=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,tex); varlevel=0; varwidth=2; varheight=1; vardata=newUint8Array([ 255,0,0,255,//aredpixel 0,255,0,255,//agreenpixel ]); gl.texImage2D(gl.TEXTURE_2D,level,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,data); Andsetthetexture'sfiltering gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); Atinitializationtimelookuptheuniformlocationintheshaderprogram varsomeSamplerLoc=gl.getUniformLocation(someProgram,"u_texture"); Atrendertimebindthetexturetoatextureunit varunit=5;//Picksometextureunit gl.activeTexture(gl.TEXTURE0+unit); gl.bindTexture(gl.TEXTURE_2D,tex); Andtelltheshaderwhichunityouboundthetextureto gl.uniform1i(someSamplerLoc,unit); Varyings Avaryingisawaytopassavaluefromavertexshadertoafragmentshaderwhichwe coveredinhowitworks. Touseavaryingweneedtodeclarematchingvaryingsinbothavertexandfragmentshader. Wesetthevaryinginthevertexshaderwithsomevaluepervertex.WhenWebGLdrawspixels itwillinterpolatebetweenthosevaluesandpassthemtothecorrespondingvaryingin thefragmentshader Vertexshader attributevec4a_position; uniformvec4u_offset; +varyingvec4v_positionWithOffset; voidmain(){ gl_Position=a_position+u_offset; +v_positionWithOffset=a_position+u_offset; } Fragmentshader precisionmediumpfloat; +varyingvec4v_positionWithOffset; voidmain(){ +//convertfromclipspace(-1+1)tocolorspace(0->1). +vec4color=v_positionWithOffset*0.5+0.5 +gl_FragColor=color; } Theexampleaboveisamostlynonsenseexample.Itdoesn'tgenerallymakesenseto directlycopytheclipspacevaluestothefragmentshaderandusethemascolors.Nevertheless itwillworkandproducecolors. GLSL GLSLstandsforGraphicsLibraryShaderLanguage.It'sthelanguageshadersarewritten in.IthassomespecialsemiuniquefeaturesthatarecertainlynotcommoninJavaScript. It'sdesignedtodothemaththatiscommonlyneededtocomputethingsforrasterizing graphics.Soforexampleithasbuiltintypeslikevec2,vec3,andvec4which represent2values,3values,and4valuesrespectively.Similarlyithasmat2,mat3 andmat4whichrepresent2x2,3x3,and4x4matrices.Youcandothingslikemultiply avecbyascalar. vec4a=vec4(1,2,3,4); vec4b=a*2.0; //bisnowvec4(2,4,6,8); Similarlyitcandomatrixmultiplicationandvectortomatrixmultiplication mat4a=??? mat4b=??? mat4c=a*b; vec4v=??? vec4y=c*v; Italsohasvariousselectorsforthepartsofavec.Foravec4 vec4v; v.xisthesameasv.sandv.randv[0]. v.yisthesameasv.tandv.gandv[1]. v.zisthesameasv.pandv.bandv[2]. v.wisthesameasv.qandv.aandv[3]. Itisabletoswizzleveccomponentswhichmeansyoucanswaporrepeatcomponents. v.yyyy isthesameas vec4(v.y,v.y,v.y,v.y) Similarly v.bgra isthesameas vec4(v.b,v.g,v.r,v.a) whenconstructingavecoramatyoucansupplymultiplepartsatonce.Soforexample vec4(v.rgb,1) Isthesameas vec4(v.r,v.g,v.b,1) Also vec4(1) Isthesameas vec4(1,1,1,1) Onethingyou'lllikelygetcaughtuponisthatGLSLisverytypestrict. floatf=1;//ERROR1isanint.Youcan'tassignaninttoafloat Thecorrectwayisoneofthese floatf=1.0;//usefloat floatf=float(1)//casttheintegertoafloat Theexampleaboveofvec4(v.rgb,1)doesn'tcomplainaboutthe1becausevec4is castingthethingsinsidejustlikefloat(1). GLSLhasabunchofbuiltinfunctions.Manyofthemoperateonmultiplecomponentsatonce. Soforexample Tsin(Tangle) MeansTcanbefloat,vec2,vec3orvec4.Ifyoupassinvec4yougetvec4back whichthesineofeachofthecomponents.Inotherwordsifvisavec4then vec4s=sin(v); isthesameas vec4s=vec4(sin(v.x),sin(v.y),sin(v.z),sin(v.w)); SometimesoneargumentisafloatandtherestisT.Thatmeansthatfloatwillbeapplied toallthecomponents.Forexampleifv1andv2arevec4andfisafloatthen vec4m=mix(v1,v2,f); isthesameas vec4m=vec4( mix(v1.x,v2.x,f), mix(v1.y,v2.y,f), mix(v1.z,v2.z,f), mix(v1.w,v2.w,f)); YoucanseealistofalltheGLSLfunctionsonthelastpageoftheWebGL ReferenceCard. Ifyoulikereallydryandverbosestuffyoucantry theGLSLspec. Puttingitalltogether That'sthepointofthisentireseriesofposts.WebGLisallaboutcreatingvariousshaders,supplying thedatatothoseshadersandthencallinggl.drawArraysorgl.drawElementstohaveWebGLprocess theverticesbycallingthecurrentvertexshaderforeachvertexandthenrenderpixelsbycallingthecurrentfragmentshaderforeachpixel. Actuallycreatingtheshadersrequiresseverallinesofcode.Sincethoselinesarethesamein mostWebGLprogramsandsinceoncewrittenyoucanprettymuchignorethem.HowtocompileGLSLshaders andlinkthemintoashaderprogramiscoveredhere. Ifyou'rejuststartingfromhereyoucangoin2directions.Ifyouareinterestedinimageprocessing I'llshowyouhowtodosome2Dimageprocessing. Ifyouareinterestinginlearningabouttranslation, rotation,scaleandeventually3Dthenstarthere. English Français 日本語 한국어 Polski Portuguese Русский 简体中文 Fundamentals Fundamentals HowItWorks ShadersandGLSL WebGLStateDiagram ImageProcessing ImageProcessing ImageProcessingContinued 2Dtranslation,rotation,scale,matrixmath 2DTranslation 2DRotation 2DScale 2DMatrices 3D Orthographic3D 3DPerspective 3DCameras Lighting DirectionalLighting PointLighting SpotLighting StructureandOrganization LessCode,MoreFun DrawingMultipleThings SceneGraphs Geometry Geometry-Lathe Loading.objfiles Loading.objw.mtlfiles Textures Textures DataTextures Using2orMoreTextures CrossOriginImages PerspectiveCorrectTextureMapping PlanarandPerspectiveProjectionMapping RenderingToATexture RendertoTexture Shadows Shadows Techniques 2D 2D-DrawImage 2D-MatrixStack Sprites 3D Cubemaps Environmentmaps Skyboxes Skinning Fog Picking(clickingonstuff) Text Text-HTML Text-Canvas2D Text-UsingaTexture Text-UsingaGlyphTexture Textures RampTextures(ToonShading) GPGPU GPGPU Tips SmallestPrograms DrawingWithoutData Shadertoy PullingVertices Optimization IndexedVertices(gl.drawElements) InstancedDrawing Misc SetupAndInstallation Boilerplate ResizingtheCanvas Animation Points,Lines,andTriangles MultipleViews,MultipleCanvases VisualizingtheCamera WebGLandAlpha 2Dvs3Dlibraries Anti-Patterns WebGLMatricesvsMathMatrices PrecisionIssues Takingascreenshot PreventtheCanvasBeingCleared GetKeyboardInputFromaCanvas UseWebGLasBackgroundinHTML CrossPlatformIssues QuestionsandAnswers Reference Attributes TextureUnits Framebuffers readPixels References HelperAPIDocs TWGL,AtinyWebGLhelperlibrary github Questions?Askonstackoverflow. Issue/Bug?Createanissueongithub. Use
codegoeshere
forcodeblocks
commentspoweredbyDisqus
延伸文章資訊
- 1WebGL - Shaders - Tutorialspoint
Shaders are the programs that run on GPU. Shaders are written in OpenGL ES Shader Language (known...
- 2webgl Tutorial => Getting started with webgl
At a base level WebGL is an engine that runs 2 user supplied functions on the GPU. One function i...
- 3外星圖像渲染語言?如何應用Shader 跟WebGL 達成絢麗視覺 ...
如何應用Shader 跟WebGL 達成絢麗視覺效果. 2022 年7 月7 日; creativecoding-editor. 本篇文章老闆要來聊聊什麼是Shader 、把Shader 實作在...
- 4学习WebGL之深入了解Shader - 简书
无论是Vertex Shader还是Fragment Shader,都有基本的代码框架。下面是本文使用的Vertex Shader。 attribute vec4 position; varyi...
- 5認識著色器
在〈準備WebGL Canvas〉中談到,WebGL 的組成中需要著色器程式,初學WebGL 時,著色器程式中基本上會有頂點著色器(Vertex shader)及片段著色器(Fragment s...