WebGL Shaders and GLSL

文章推薦指數: 80 %
投票人數:10人

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


請為這篇文章評分?