WebGL best practices - Web APIs | MDN
文章推薦指數: 80 %
WebGL is a complicated API, and it's often not obvious what the recommended ways to use it are. This page tackles recommendations across the ...
SkiptomaincontentSkiptosearchSkiptoselectlanguageReferencesWebAPIsWebGL:2Dand3DgraphicsforthewebWebGLbestpracticesArticleActionsEnglish(US)AddressandeliminateWebGLerrorsUnderstandextensionavailabilityUnderstandsystemlimitsAvoidinvalidatingFBOattachmentbindingsDeleteobjectseagerlyLosecontextseagerlyFlushwhenexpectingresultsAvoidblockingAPIcallsinproductionAlwaysenablevertexattrib0asanarrayEstimateaper-pixelVRAMBudgetConsiderrenderingtoasmallerbackbufferBatchdrawcallsAvoid"#ifdefGL_ES"PreferdoingworkinthevertexshaderCompileShadersandLinkProgramsinparallelPreferKHR_parallel_shader_compileDon'tcheckshadercompilestatusunlesslinkingfailsBeprecisewithGLSLprecisionannotationsPreferbuiltinsinsteadofbuildingyourownUsemipmapsforanytextureyou'llseein3dDon'tassumeyoucanrenderintofloattexturesSomeformats(e.g.RGB)maybeemulatedAvoidalpha:false,whichcanbeexpensiveConsidercompressedtextureformatsMemoryusageofdepthandstencilformatstexImage/texSubImageuploads(esp.videos)cancausepipelineflushesUsetexStoragetocreatetexturesUseinvalidateFramebufferUsenon-blockingasyncdatareadbackImageBitmapcreationRelatedTopics
WebGLAPI
WebGLtutorial
GettingstartedwithWebGL
Adding2DcontenttoaWebGLcontext
UsingshaderstoapplycolorinWebGL
AnimatingobjectswithWebGL
Creating3DobjectsusingWebGL
UsingtexturesinWebGL
LightinginWebGL
AnimatingtexturesinWebGL
Examplesandarticles
Matrixmathfortheweb
WebGLmodelviewprojection
WebGLbestpractices
UsingWebGLextensions
Abasic2DWebGLanimationexample
WebGLbyexample
Interfaces
WebGLRenderingContext
WebGL2RenderingContext
WebGLActiveInfo
WebGLBuffer
WebGLContextEvent
WebGLFramebuffer
WebGLProgram
WebGLQuery
WebGLRenderbuffer
WebGLSampler
WebGLShader
WebGLShaderPrecisionFormat
WebGLSync
WebGLTexture
WebGLTransformFeedback
WebGLUniformLocation
WebGLVertexArrayObject
Documentation:
Contribute
TheMDNproject
AddressandeliminateWebGLerrorsUnderstandextensionavailabilityUnderstandsystemlimitsAvoidinvalidatingFBOattachmentbindingsDeleteobjectseagerlyLosecontextseagerlyFlushwhenexpectingresultsAvoidblockingAPIcallsinproductionAlwaysenablevertexattrib0asanarrayEstimateaper-pixelVRAMBudgetConsiderrenderingtoasmallerbackbufferBatchdrawcallsAvoid"#ifdefGL_ES"PreferdoingworkinthevertexshaderCompileShadersandLinkProgramsinparallelPreferKHR_parallel_shader_compileDon'tcheckshadercompilestatusunlesslinkingfailsBeprecisewithGLSLprecisionannotationsPreferbuiltinsinsteadofbuildingyourownUsemipmapsforanytextureyou'llseein3dDon'tassumeyoucanrenderintofloattexturesSomeformats(e.g.RGB)maybeemulatedAvoidalpha:false,whichcanbeexpensiveConsidercompressedtextureformatsMemoryusageofdepthandstencilformatstexImage/texSubImageuploads(esp.videos)cancausepipelineflushesUsetexStoragetocreatetexturesUseinvalidateFramebufferUsenon-blockingasyncdatareadbackImageBitmapcreationWebGLbestpracticesWebGLisacomplicatedAPI,andit'softennotobviouswhattherecommendedwaystouseitare.Thispagetacklesrecommendationsacrossthespectrumofexpertise,andnotonlyhighlightsdosanddon'ts,butalsodetailswhy.Youcanrelyonthisdocumenttoguideyourchoiceofapproach,andensureyou'reontherighttracknomatterwhatbrowserorhardwareyourusersrun.AddressandeliminateWebGLerrorsYourapplicationshouldrunwithoutgeneratinganyWebGLerrors(asreturnedbygetError).EveryWebGLerrorisreportedintheWebConsoleasaJavaScriptwarningwithadescriptivemessage.Aftertoomanyerrors(32inFirefox),WebGLstopsgeneratingdescriptivemessages,whichreallyhindersdebugging.
Theonlyerrorsawell-formedpagegeneratesareOUT_OF_MEMORYandCONTEXT_LOST.UnderstandextensionavailabilityTheavailabilityofmostWebGLextensionsdependsontheclientsystem.WhenusingWebGLextensions,ifpossible,trytomakethemoptionalbygracefullyadaptingtothecasetheretheyarenotsupported.
TheseWebGL1extensionsareuniversallysupported,andcanbereliedupontobepresent:
ANGLE_instanced_arrays
EXT_blend_minmax
OES_element_index_uint
OES_standard_derivatives
OES_vertex_array_object
WEBGL_debug_renderer_info
WEBGL_lose_context
(seealso:https://jdashg.github.io/misc/webgl/webgl-feature-levels.html)
ConsiderpolyfillingtheseintoWebGLRenderingContext,like:https://github.com/jdashg/misc/blob/master/webgl/webgl-v1.1.jsUnderstandsystemlimitsSimilarlytoextensions,thelimitsofyoursystemwillbedifferentthanyourclients'systems!Don'tassumeyoucanusethirtytexturesamplerspershaderjustbecauseitworksonyourmachine!
TheminimumrequirementsforWebGLarequitelow.Inpractice,effectivelyallsystemssupportatleastthefollowing:
MAX_CUBE_MAP_TEXTURE_SIZE:4096
MAX_RENDERBUFFER_SIZE:4096
MAX_TEXTURE_SIZE:4096
MAX_VIEWPORT_DIMS:[4096,4096]
MAX_VERTEX_TEXTURE_IMAGE_UNITS:4
MAX_TEXTURE_IMAGE_UNITS:8
MAX_COMBINED_TEXTURE_IMAGE_UNITS:8
MAX_VERTEX_ATTRIBS:16
MAX_VARYING_VECTORS:8
MAX_VERTEX_UNIFORM_VECTORS:128
MAX_FRAGMENT_UNIFORM_VECTORS:64
ALIASED_POINT_SIZE_RANGE:[1,100]
Yourdesktopmaysupport16ktextures,ormaybe16textureunitsinthevertexshader,butmostothersystemsdon't,andcontentthatworksforyouwillnotworkforthem!AvoidinvalidatingFBOattachmentbindingsAlmostanychangetoanFBO'sattachmentbindingswillinvalidateitsframebuffercompleteness.Setupyourhotframebuffersaheadoftime.
InFirefox,settingtheprefwebgl.perf.max-warningsto-1inabout:configwillenableperformancewarningsthatincludewarningsaboutFBcompletenessinvalidations.AvoidchangingVAOattachments(vertexAttribPointer,disable/enableVertexAttribArray)Drawingfromstatic,unchangingVAOsisfasterthanmutatingthesameVAOforeverydrawcall.ForunchangedVAOs,browserscancachethefetchlimits,whereaswhenVAOschange,browsersmustrevalidateandrecalculatelimits.Theoverheadforthisisrelativelylow,butre-usingVAOsmeansfewervertexAttribPointercallstoo,soit'sworthdoingwhereverit'seasy.DeleteobjectseagerlyDon'twaitforthegarbagecollector/cyclecollectortorealizeobjectsareorphanedanddestroythem.Implementationstrackthelivenessofobjects,so'deleting'themattheAPIlevelonlyreleasesthehandlethatreferstotheactualobject.(conceptuallyreleasingthehandle'sref-pointertotheobject)Onlyoncetheobjectisunusedintheimplementationisitactuallyfreed.Forexample,ifyouneverwanttoaccessyourshaderobjectsdirectlyagain,justdeletetheirhandlesafterattachingthemtoaprogramobject.LosecontextseagerlyConsideralsoeagerlylosingWebGLcontextsviatheWEBGL_lose_contextextensionwhenyou'redefinitelydonewiththemandnolongerneedthetargetcanvas'srenderingresults.Notethatthisisnotnecessarytodowhennavigatingawayfromapage-don'taddanunloadeventhandlerjustforthispurpose.FlushwhenexpectingresultsCallflush()whenexpectingresultssuchasqueries,oratcompletionofarenderingframe.
Flushtellstheimplementationtopushallpendingcommandsoutforexecution,flushingthemoutofthequeue,insteadofwaitingformorecommandstoenqueuebeforesendingforexecution.
Forexample,itispossibleforthefollowingtonevercompletewithoutcontextloss:
sync=glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE,0);
glClientWaitSync(sync,0,GL_TIMEOUT_IGNORED);
WebGLdoesn'thaveaSwapBufferscallbydefault,soaflushcanhelpfillthegap,aswell.Usewebgl.flush()whennotusingrequestAnimationFrameWhennotusingRAF,(suchaswhenusingRPAF;seebelow)usewebgl.flush()toencourageeagerexecutionofenqueuedcommands.
BecauseRAFisdirectlyfollowedbytheframeboundary,anexplicitwebgl.flush()isn'treallyneededwithRAF.AvoidblockingAPIcallsinproductionCertainWebGLentrypoints-includinggetErrorandgetParameter-causesynchronousstallsonthecallingthread.Evenbasicrequestscantakeaslongas1ms,buttheycantakeevenlongeriftheyneedtowaitforallgraphicsworktobecompleted(withaneffectsimilartoglFinish()innativeOpenGL).
Inproductioncode,avoidsuchentrypoints,especiallyonthebrowsermainthreadwheretheycancausetheentirepagetojank(oftenincludingscrollingoreventhewholebrowser).
getError():causesaflush+round-triptofetcherrorsfromtheGPUprocess).
Forexample,withinFirefox,theonlytimeglGetErrorischeckedisafterallocations(bufferData,*texImage*,texStorage*)topickupanyGL_OUT_OF_MEMORYerrors.
getShader/ProgramParameter(),getShader/ProgramInfoLog(),othergetsonshaders/programs:flush+shadercompile+round-trip,ifnotdoneaftershadercompilationiscomplete.(Seealsoparallelshadercompilationbelow.)
get*Parameter()ingeneral:possibleflush+round-trip.Insomecases,thesewillbecachedtoavoidtheround-trip,buttrytoavoidrelyingonthis.
checkFramebufferStatus():possibleflush+round-trip.
getBufferSubData():usualfinish+round-trip.(ThisisokayforREADbuffersinconjunctionwithfences-seeasyncdatareadbackbelow.)
readPixels()totheCPU(i.e.withoutanUNPACKbufferbound):finish+round-trip.Instead,useGPU-GPUreadPixelsinconjunctionwithasyncdatareadback.
Alwaysenablevertexattrib0asanarrayIfyoudrawwithoutvertexattrib0enabledasanarray,youwillforcethebrowsertodocomplicatedemulationwhenrunningondesktopOpenGL(suchasonmacOS).ThisisbecauseindesktopOpenGL,nothinggetsdrawnifvertexattrib0isnotarray-enabled.YoucanusebindAttribLocationtoforceavertexattributetouselocation0,anduseenableVertexAttribArray(0)tomakeitarray-enabled.Estimateaper-pixelVRAMBudgetWebGLdoesn'tofferAPIstoquerythemaximumamountofvideomemoryonthesystembecausesuchqueriesarenotportable.Still,applicationsmustbeconsciousofVRAMusageandnotjustallocateasmuchaspossible.
OnetechniquepioneeredbytheGoogleMapsteamisthenotionofaper-pixelVRAMbudget:
1)Foronesystem(e.g.aparticulardesktop/laptop),decidethemaximumamountofVRAMyourapplicationshoulduse.2)Computethenumberofpixelscoveredbyamaximizedbrowserwindow.E.g.(window.innerWidth*devicePixelRatio)*(window.innerHeight*window.devicePixelRatio)3)Theper-pixelVRAMbudgetis(1)dividedby(2),andisaconstant.
Thisconstantshouldgenerallybeportableamongsystems.Mobiledevicestypicallyhavesmallerscreensthanpowerfuldesktopmachineswithlargemonitors.Re-computethisconstantonafewtargetsystemstogetareliableestimate.
Nowadjustallinternalcachingintheapplication(WebGLBuffers,WebGLTextures,etc.)toobeyamaximumsize,computedbythisconstantmultipliedbythenumberofpixelscoveredbythecurrentbrowserwindow.Thisrequiresestimatingthenumberofbytesconsumedbyeachtexture,forexample.Thecapalsomusttypicallybeupdatedasthebrowserwindowresizes,andolderresourcesabovethelimitmustbepurged.
Keepingtheapplication'sVRAMusageunderthiscapwillhelptoavoidout-of-memoryerrorsandassociatedinstability.ConsiderrenderingtoasmallerbackbufferAcommon(andeasy)waytotradeoffqualityforspeedisrenderingintoasmallerbackbuffer,andupscalingtheresult.Considerreducingcanvas.widthandheightandkeepingcanvas.style.widthandheightataconstantsize.Batchdrawcalls"Batching"drawcallsintofewer,largerdrawcallswillgenerallyimproveperformance.Ifyouhave1000spritestopaint,trytodoitasasingledrawArrays()ordrawElements()call.
It'scommontouse"degeneratetriangles"ifyouneedtodrawdiscontinuousobjectsasasingledrawArrays(TRIANGLE_STRIP)call.Degeneratetrianglesaretriangleswithnoarea,thereforeanytrianglewheremorethanonepointisinthesameexactlocation.Thesetrianglesareeffectivelyskipped,whichletsyoustartanewtrianglestripunattachedtoyourpreviousone,withouthavingtosplitintomultipledrawcalls.
Anotherimportantmethodforbatchingistextureatlasing,wheremultipleimagesareplacedintoasingletexture,oftenlikeacheckerboard.Sinceyouneedtosplitdrawcallbatchestochangetextures,textureatlasingletsyoucombinemoredrawcallsintofewer,biggerbatches.Seethisexampledemonstratinghowtocombineevenspritesreferencingmultipletextureatlasesintoasingledrawcall.Avoid"#ifdefGL_ES"Youshouldneveruse#ifdefGL_ESinyourWebGLshaders;thisconditionisalwaystrueinWebGL.Althoughsomeearlyexamplesusedthis,it'snotnecessary.PreferdoingworkinthevertexshaderDoasmuchworkasyoucaninthevertexshader,ratherthaninthefragmentshader.Thisisbecauseperdrawcall,fragmentshadersgenerallyrunmanymoretimesthanvertexshaders.Anycalculationthatcanbedoneontheverticesandthenjustinterpolatedamongfragments(viavaryings)isaperformanceboon.(Theinterpolationofvaryingsisverycheap,andisdoneautomaticallyforyouthroughthefixedfunctionalityrasterizationphaseofthegraphicspipeline.)
Forexample,asimpleanimationofatexturedsurfacecanbeachievedthroughatime-dependenttransformationoftexturecoordinates.(Thesimplestcasebeingaddingauniformvectortothetexturecoordinatesattributevector)Ifvisuallyacceptable,onecantransformthetexturecoordinatesinthevertexshaderratherthaninthefragmentshader,togetbetterperformance.
Onecommontrade-offistosomelightingcalculationsper-vertexinsteadofper-fragment(pixel).Insomecases,especiallywithsimplemodelsordensevertices,thislooksgoodenough.
Theinversionofthisisifamodelhasmoreverticesthanpixelsintherenderedoutput.However,LODmeshesisusuallytheanswertothisproblem,rarelymovingworkfromthevertextothefragmentshader.CompileShadersandLinkProgramsinparallelIt'stemptingtocompileshadersandlinkprogramsserially,butmanybrowserscancompileandlinkinparallelonbackgroundthreads.
Insteadof:
functioncompileOnce(gl,shader){
if(shader.compiled)return;
gl.compileShader(shader);
shader.compiled=true;
}
for(const[vs,fs,prog]ofprograms){
compileOnce(gl,vs);
compileOnce(gl,fs);
gl.linkProgram(prog);
if(!gl.getProgramParameter(prog,gl.LINK_STATUS)){
console.error('Linkfailed:'+gl.getProgramInfoLog(prog));
console.error('vsinfo-log:'+gl.getShaderInfoLog(vs));
console.error('fsinfo-log:'+gl.getShaderInfoLog(fs));
}
}
Consider:
functioncompileOnce(gl,shader){
if(shader.compiled)return;
gl.compileShader(shader);
shader.compiled=true;
}
for(const[vs,fs,prog]ofprograms){
compileOnce(gl,vs);
compileOnce(gl,fs);
}
for(const[vs,fs,prog]ofprograms){
gl.linkProgram(prog);
}
for(const[vs,fs,prog]ofprograms){
if(!gl.getProgramParameter(prog,gl.LINK_STATUS)){
console.error('Linkfailed:'+gl.getProgramInfoLog(prog));
console.error('vsinfo-log:'+gl.getShaderInfoLog(vs));
console.error('fsinfo-log:'+gl.getShaderInfoLog(fs));
}
}
PreferKHR_parallel_shader_compileWhilewe'vedescribedapatterntoallowbrowserstocompileandlinkinparallel,normallycheckingCOMPILE_STATUSorLINK_STATUSblocksuntilthecompileorlinkcompletes.Inbrowserswhereit'savailable,theKHR_parallel_shader_compileextensionprovidesanon-blockingCOMPLETION_STATUSquery.Prefertoenableandusethisextension.
Exampleusage:
ext=gl.getExtension('KHR_parallel_shader_compile');
gl.compileProgram(vs);
gl.compileProgram(fs);
gl.attachShader(prog,vs);
gl.attachShader(prog,fs);
gl.linkProgram(prog);
//Storeprograminyourdatastructure.
//Later,forexamplethenextframe:
if(ext){
if(gl.getProgramParameter(prog,ext.COMPLETION_STATUS_KHR)){
//Checkprogramlinkstatus;ifOK,useanddrawwithit.
}
}else{
//Programlinkingissynchronous.
//Checkprogramlinkstatus;ifOK,useanddrawwithit.
}
Thistechniquemaynotworkinallapplications,forexamplethosewhichrequireprogramstobeimmediatelyavailableforrendering.Still,considerhowvariationsmaywork.Don'tcheckshadercompilestatusunlesslinkingfailsThereareveryfewerrorsthatareguaranteedtocauseshadercompilationfailure,butcannotbedeferredtolinktime.TheESSL3specsaysthisunder"ErrorHandling":
Theimplementationshouldreporterrorsasearlyapossiblebutinanycasemustsatisfythefollowing:
Alllexical,grammaticalandsemanticerrorsmusthavebeendetectedfollowingacalltoglLinkProgram
Errorsduetomismatchbetweenthevertexandfragmentshader(linkerrors)musthavebeendetectedfollowingacalltoglLinkProgram
ErrorsduetoexceedingresourcelimitsmusthavebeendetectedfollowinganydrawcalloracalltoglValidateProgram
AcalltoglValidateProgrammustreportallerrorsassociatedwithaprogramobjectgiventhecurrentGLstate.
Theallocationoftasksbetweenthecompilerandlinkerisimplementationdependent.Consequentlytherearemanyerrorswhichmaybedetectedeitheratcompileorlinktime,dependingontheimplementation.
Additionally,queryingcompilestatusisasynchronouscall,whichbreakspipelining.
Insteadof:
gl.compileShader(vs);
if(!gl.getShaderParameter(vs,gl.COMPILE_STATUS)){
console.error('vscompilefailed:'+gl.getShaderInfoLog(vs));
}
gl.compileShader(fs);
if(!gl.getShaderParameter(fs,gl.COMPILE_STATUS)){
console.error('fscompilefailed:'+gl.getShaderInfoLog(fs));
}
gl.linkProgram(prog);
if(!gl.getProgramParameter(vs,gl.LINK_STATUS)){
console.error('Linkfailed:'+gl.getProgramInfoLog(prog));
}
Consider:
gl.compileShader(vs);
gl.compileShader(fs);
gl.linkProgram(prog);
if(!gl.getProgramParameter(vs,gl.LINK_STATUS)){
console.error('Linkfailed:'+gl.getProgramInfoLog(prog));
console.error('vsinfo-log:'+gl.getShaderInfoLog(vs));
console.error('fsinfo-log:'+gl.getShaderInfoLog(fs));
}
BeprecisewithGLSLprecisionannotationsIfyouexpecttopassanessl300intbetweenshaders,andyouneedittohave32-bits,youmustusehighporyouwillhaveportabilityproblems.(WorksonDesktop,notonAndroid)
Ifyouhaveafloattexture,iOSrequiresthatyouusehighpsampler2Dfoo;,oritwillverypainfullygiveyoulowptexturesamples!(+/-2.0maxisprobablynotgoodenoughforyou)ImplicitdefaultsThevertexlanguagehasthefollowingpredeclaredgloballyscopeddefaultprecisionstatements:
precisionhighpfloat;
precisionhighpint;
precisionlowpsampler2D;
precisionlowpsamplerCube;
Thefragmentlanguagehasthefollowingpredeclaredgloballyscopeddefaultprecisionstatements:
precisionmediumpint;
precisionlowpsampler2D;
precisionlowpsamplerCube;
InWebGL1,"highpfloat"supportisoptionalinfragmentshadersUsinghighpprecisionunconditionallyinfragmentshaderswillpreventyourcontentfromworkingonsomeoldermobilehardware.
Whileyoucanusemediumpfloatinstead,butbeawarethatthisoftenresultsincorruptedrenderingduetolackofprecision(particularlymobilesystems)thoughthecorruptionisnotgoingtobevisibleonatypicaldesktopcomputer.
Ifyouknowyourprecisionrequirements,getShaderPrecisionFormat()willtellyouwhatthesystemsupports.
Ifhighpfloatisavailable,GL_FRAGMENT_PRECISION_HIGHwillbedefinedas1.
Agoodpatternfor"alwaysgivemethehighestprecision":
#ifdefGL_FRAGMENT_PRECISION_HIGH
precisionhighpfloat;
#else
precisionmediumpfloat;
#endif
ESSL100minimumrequirements(WebGL1)
float
think
range
minabovezero
precision
highp
float24*
(-2^62,2^62)
2^-62
2^-16relative
mediump
IEEEfloat16
(-2^14,2^14)
2^-14
2^-10relative
lowp
10-bitsignedfixed
(-2,2)
2^-8
2^-8absolute
int
think
range
highp
int17
(-2^16,2^16)
mediump
int11
(-2^10,2^10)
lowp
int9
(-2^8,2^8)
*float24:signbit,7-bitforexponent,16-bitformantissaESSL300minimumrequirements(WebGL2)
float
think
range
minabovezero
precision
highp
IEEEfloat32
(-2^126,2^127)
2^-126
2^-24relative
mediump
IEEEfloat16
(-2^14,2^14)
2^-14
2^-10relative
lowp
10-bitsignedfixed
(-2,2)
2^-8
2^-8absolute
(u)int
think
intrange
unsignedintrange
highp
(u)int32
[-2^31,2^31]
[0,2^32]
mediump
(u)int16
[-2^15,2^15]
[0,2^16]
lowp
(u)int9
[-2^8,2^8]
[0,2^9]
PreferbuiltinsinsteadofbuildingyourownPreferbuiltinslikedot,mix,andnormalize.Atbest,customimplementationsmightrunasfastasthebuiltinstheyreplace,butdon'texpectthemto.Hardwareoftenhashyper-optimizedorevenspecializedinstructionsforbuiltins,andthecompilercan'treliablyreplaceyourcustombuiltin-replacementswiththespecialbuiltincodepaths.Usemipmapsforanytextureyou'llseein3dWhenindoubt,callgenerateMipmaps()aftertextureuploads.Mipmapsarecheaponmemory(only30%overhead)whileprovidingoften-largeperformanceadvantageswhentexturesare"zoomedout"orgenerallydownscaledinthedistancein3d,orevenforcube-maps!
It'squickertosamplefromsmallertextureimagesduetobetterinherenttexturefetchcachelocality:Zoomingoutonanon-mipmappedtextureruinstexturefetchcachelocality,becauseneighboringpixelsnolongersamplefromneighboringtexels!
However,for2dresourcesthatarenever"zoomedout",don'tpaythe30%memorysurchargeformipmaps:
consttex=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.texParameterf(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//DefaultstoNEAREST_MIPMAP_LINEAR,formipmapping!
(InWebGL2,youshouldjustusetexStoragewithlevels=1)
Onecaveat:generateMipmapsonlyworksifyouwouldbeabletorenderintothetextureifyouattachedittoaframebuffer.(Thespeccallsthis"color-renderableformats")Forexample,ifasystemsupportsfloat-texturesbutnotrender-to-float,generateMipmapswillfailforfloatformats.Don'tassumeyoucanrenderintofloattexturesTherearemany,manysystemsthatsupportRGBA32Ftextures,butifyouattachonetoaframebufferyou'llgetFRAMEBUFFER_INCOMPLETE_ATTACHMENTfromcheckFramebufferStatus().Itmayworkonyoursystem,butmostmobilesystemswillnotsupportit!
OnWebGL1,usetheEXT_color_buffer_half_floatandWEBGL_color_buffer_floatextensionstocheckforrender-to-float-texturesupportforfloat16andfloat32respectively.
OnWebGL2,EXT_color_buffer_floatchecksforrender-to-float-texturesupportforbothfloat32andfloat16.EXT_color_buffer_half_floatispresentonsystemswhichonlysupportrenderingtofloat16textures.Render-to-float32doesn'timplyfloat32-blending!Itmayworkonyoursystem,butonmanyothersitwon't.Avoiditifyoucan.CheckfortheEXT_float_blendextensiontocheckforsupport.
Float16-blendingisalwayssupported.Someformats(e.g.RGB)maybeemulatedAnumberofformats(particularlythree-channelformats)areemulated.Forexample,RGB32FisoftenactuallyRGBA32F,andLuminance8mayactuallybeRGBA8.RGB8inparticularisoftensurprisinglyslow,asmaskingoutthealphachanneland/orpatchingblendfunctionshasfairlyhighoverhead.PrefertouseRGBA8andignorethealphayourselfforbetterperformance.Avoidalpha:false,whichcanbeexpensiveSpecifyingalpha:falseduringcontextcreationcausesthebrowsertocompositetheWebGL-renderedcanvasasthoughitwereopaque,ignoringanyalphavaluestheapplicationwritesinitsfragmentshader.Onsomeplatforms,thiscapabilityunfortunatelycomesatasignificantperformancecost.TheRGBbackbuffermayhavetobeemulatedontopofanRGBAsurface,andtherearerelativelyfewtechniquesavailableintheOpenGLAPIformakingitappeartotheapplicationthatanRGBAsurfacehasnoalphachannel.Ithasbeenfoundthatallofthesetechniqueshaveapproximatelyequalperformanceimpactonaffectedplatforms.
Mostapplications,eventhoserequiringalphablending,canbestructuredtoproduce1.0forthealphachannel.Theprimaryexceptionisanyapplicationrequiringdestinationalphaintheblendingfunction.Iffeasible,itisrecommendedtodothisratherthanusingalpha:false.ConsidercompressedtextureformatsWhileJPGandPNGaregenerallysmallerover-the-wire,GPUcompressedtextureformatsaresmalleroninGPUmemory,andarefastertosamplefrom.(Thisreducestexturememorybandwidth,whichispreciousonmobile)However,compressedtextureformatshaveworsequalitythanJPG,andaregenerallyonlyacceptableforcolors(note.g.normalsorcoordinates).
Unfortunately,there'snosingleuniversallysupportedformat.Everysystemhasatleastoneofthefollowingthough:
WEBGL_compressed_texture_s3tc(desktop)
WEBGL_compressed_texture_etc1(Android)
WEBGL_compressed_texture_pvrtc(iOS)
WebGL2hasuniversalsupportbycombining:
WEBGL_compressed_texture_s3tc(desktop)
WEBGL_compressed_texture_etc(mobile)
WEBGL_compressed_texture_astchasbothhigherqualityand/orhighercompression,butisonlysupportedonnewerhardware.BasisUniversaltexturecompressionformat/libraryBasisUniversalsolvesseveraloftheissuesmentionedabove.Itoffersawaytosupportallcommoncompressedtextureformatswithasinglecompressedtexturefile,throughaJavaScriptlibrarythatefficientlyconvertsformatsatloadtime.ItalsoaddsadditionalcompressionthatmakesBasisUniversalcompressedtexturefilesmuchsmallerthanregularcompressedtexturesover-the-wire,morecomparabletoJPEG.
https://github.com/BinomialLLC/basis_universal/blob/master/webgl/README.mdMemoryusageofdepthandstencilformatsDepthandstencilattachmentsandformatsareactuallyinseparableonmanydevices.YoumayaskforDEPTH_COMPONENT24orSTENCIL_INDEX8,butyou'reoftengettingD24X8andX24S832bppformatsbehindthescenes.Assumethatthememoryusageofdepthandstencilformatsisroundeduptothenearestfourbytes.texImage/texSubImageuploads(esp.videos)cancausepipelineflushesMosttextureuploadsfromDOMelementswillincuraprocessingpassthatwilltemporarilyswitchGLProgramsinternally,causingapipelineflush.(PipelinesareformalizedexplicitlyinVulkan[1]etal,butareimplicitbehind-the-scenesinOpenGLandWebGL.Pipelinesaremoreorlessthetupleofshaderprogram,depth/stencil/multisample/blend/rasterizationstate)
InWebGL:
...
useProgram(prog1)
延伸文章資訊
- 1WebGL best practices - Web APIs | MDN
WebGL is a complicated API, and it's often not obvious what the recommended ways to use it are. T...
- 2Using WebGL extensions - Web APIs | MDN
WebGL, like its sister APIs (OpenGL and OpenGL ES), supports extensions. A complete list of exten...
- 3WebGL - Web APIs | MDN
WebGL (Web Graphics Library) 是一個透過瀏覽器渲染3D及2D圖像的 JavaScript API ,且不需要安裝任何插件。 WebGL 透過與OpenGL ES 2....
- 4检测WebGL - Web API 接口参考
了解更多并加入MDN Web Docs 社区。 检测WebGL. WebGL特性检测.
- 5Using textures in WebGL - Web APIs | MDN