Shader: vad är det, typer av shader och hur de fungerar

Författare: IT Sectr Publicerad: 2026-06-11 Lästid: 8 min

Shader (shader) — är ett program som körs på GPU för att bearbeta grafisk data: vertexar, fragment eller beräkningsuppgifter. Till skillnad från vanlig kod på CPU arbetar en shader parallellt på hundratals kärnor och bearbetar varje element oberoende. Enligt Khronos Group (2025) används shaders i 100% av moderna 3D-applikationer — från mobila spel till UI-effekter i systemapplikationer. Utvecklare skriver shaders i specialiserade språk: GLSL, HLSL, Metal Shading Language eller SPIR-V.

Huvudpunkter

  • Shader — program för GPU, som körs parallellt på hundratals kärnor för varje element i scenen.
  • Typer av shaders: vertex-, fragment-, compute-, geometry-, tessellation- och mesh-shaders.
  • Språk: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — alla kompileras till GPU-maskinkod.
  • Shaders i mobil utveckling används för effekter, efterbehandling, belysning och beräkningar.
  • Optimering av shaders: mediump-precision, minimering av förgreningar och ATF (Adaptive Texture Fetch) för mobila GPU:er.

Vad är Shader?

Shader — är ett litet program, skrivet på ett specialiserat språk och kört på GPU. Varje shader bearbetar ett dataelement — en vertex, ett fragment (pixel) eller ett arbetselement — oberoende av andra. GPU:ns parallellism gör det möjligt att köra tusentals shader-instanser samtidigt.

Termen introducerades av Pixar på 1980-talet för att beskriva program som styr utseendet på ytor i RenderMan. I realtid dök shaders upp med NVIDIA GeForce 3 (2001) — det första grafikkortet med programmerbar pipeline. Före shaders konfigurerades grafik via fasta parametrar: färg, textur, blandningsläge.

Enligt Unity Technologies (2025) använder ett genomsnittligt mobilt spel 50–200 shaders. Varje shader har varianter (variants) för olika plattformar, kvalitetsnivåer och belysningskonfigurationer. Antalet varianter kan nå 10 000 per projekt.

Shaderarkitekturen delas in i indata (attribut, uniform-variabler, texturer), programkod och utdata (färg, position). Uniform-variabler ställs in från CPU innan shadern startas och är oförändrade för alla element i bildrutan. Attribut är data per element (vertexkoordinater, normal, UV-koordinater).

SIMT-exekveringsmodell

SIMT (Single Instruction, Multiple Threads) — exekveringsmodell för shaders på GPU. En instruktion laddas en gång men exekveras av hundratals trådar på olika data. Till exempel, Fragment Shader för 1000 pixlar startar 1000 trådar med samma kod, men varje tråd får sina egna UV-koordinater och interpolerade attribut.

En viktig konsekvens av SIMT: förgreningar i shaders är dyra. Om hälften av trådarna går en gren och hälften en annan inom ett if-block, kör GPU båda grenarna sekventiellt för alla trådar. Prestandan sjunker till 50%. Undvik dynamiska förgreningar i shaders eller minimera dem genom förberäkningar på CPU.

Typer av shaders

Moderna GPU:er stöder flera typer av shaders, var och en för sitt eget stadium i den grafiska eller beräkningsmässiga pipelinen. Låt oss titta på huvudtyperna: vertex-, fragment-, compute- och moderna mesh-shaders.

ShadertypPipeline-stadiumBearbetarSpråk
Vertex ShaderVertexVarje vertexGLSL, HLSL
Fragment ShaderFragmentVarje pixelGLSL, HLSL
Compute ShaderBeräkningsGodtycklig dataGLSL, HLSL
Geometry ShaderGeometriskPrimitiverGLSL, HLSL
Tessellation ShaderTesselleringPatcharGLSL, HLSL
Mesh ShaderMesh-pipelineTask + MeshHLSL, MSL

Vertex Shader

Vertex Shader bearbetar varje vertex i geometrin: transformerar koordinater, beräknar belysning, skickar data till fragment shadern. Detta är ett obligatoriskt stadium i den grafiska pipelinen — utan det når inte vertexarna skärmen. Vertex Shader anropas för varje vertex i varje bildruta.

Fragment Shader

Fragment Shader (eller Pixel Shader) — det mest resurskrävande stadiet. Det beräknar slutfärgen för varje fragment med hjälp av texturer, belysning och material. Fragment Shader exekveras för varje pixel som täcks av geometri, med hänsyn till alla applicerade texturer och effekter. Optimering av denna shader ger den största prestandaökningen.

Compute Shader

Compute Shader — universell shader för godtyckliga beräkningar på GPU. Till skillnad från grafiska shaders är den inte bunden till geometri eller pixlar. Compute Shader arbetar med godtyckliga databuffertar via arbetsgrupper. Används för fysik, partikelsimulering, post-effekter och slutledning av neurala nätverk.

Mesh Shader

Mesh Shader — den nyaste shadertypen, som dök upp i NVIDIA Turing (2018) och Metal 3. Mesh Shader ersätter vertex-, geometri- och tesselleringsshaders med en enda mesh-pipeline. Arbetar tillsammans med Task Shader: Task Shader bestämmer vilka mesh-grupper som ska renderas, Mesh Shader genererar geometri i farten.

Språk för att skriva shaders

Shaders skrivs på specialiserade språk som kompileras till GPU-maskinkod. Valet av språk beror på plattform och API. Låt oss titta på huvudspråken: GLSL, HLSL, Metal Shading Language och mellanformatet SPIR-V.

GLSL (OpenGL Shading Language)

GLSL — shaderspråket för OpenGL, OpenGL ES och WebGL. Syntaxen är baserad på C med tillägg av vektortyper (vec2, vec4, mat4) och inbyggda funktioner (texture, normalize, reflect). GLSL ES — versionen för mobila enheter med begränsad precision (lowp, mediump, highp). Enligt Khronos (2025) förblir GLSL det mest spridda shaderspråket tack vare sin cross-plattformsförmåga.

glsl
#version 300 es
precision mediump float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 fragColor;

void main() {
    fragColor = texture(u_texture, v_texCoord);
}

En enkel fragment shader läser färg från en textur baserat på UV-koordinater. precision mediump instruerar GPU:n att använda halv precision för float — påskyndar exekvering på mobila enheter med 25–40%.

HLSL (High-Level Shader Language)

HLSL — Microsofts shaderspråk för DirectX. Syntaxen ligger närmare C++ med stöd för klasser, strukturer och mallar. HLSL används i Windows-applikationer och stöder via Shader Model 6.7+ Ray Tracing, Mesh Shaders och Sampler Feedback. För mobil utveckling används HLSL inte direkt, men kompileras till SPIR-V för Vulkan.

Metal Shading Language

MSL (Metal Shading Language) — Apples shaderspråk, baserat på C++14. Till skillnad från GLSL och HLSL kompileras MSL tillsammans med applikationen, vilket eliminerar JIT-kompilering på enheten. MSL stöder pekare, mallar och C++ standardbibliotek. Används på alla Apple-enheter: iPhone, iPad, Mac, Apple TV.

cpp
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
    float4 position [[position]];
    float2 texCoord;
};

fragment float4
myFragment(VertexOut in [[stage_in]],
            texture2d<float> tex [[texture(0)]]) {
    constexpr sampler s = sampler(filter::linear);
    return tex.sample(s, in.texCoord);
}

MSL använder attributen [[position]], [[stage_in]] och [[texture(N)]] för att binda resurser. Apples kompilator genererar optimerad kod för den aktuella GPU:n med hänsyn till antalet register och cache.

SPIR-V

SPIR-V — mellanliggande binärt format för shaders, standard för Vulkan. Shaders skrivs i GLSL eller HLSL, kompileras till SPIR-V och laddas i Vulkan-applikationen. SPIR-V är inte bundet till ett specifikt språk — det finns kompilatorer från Rust, Python, OpenCL C till SPIR-V.

Shaders i mobil utveckling

Shaders på mobila plattformar har begränsningar jämfört med stationära: färre register, begränsad precision och brist på stöd för vissa instruktioner. Låt oss titta på specifikationen för shaders på Android (Vulkan/OpenGL ES) och iOS (Metal).

Shaders på Android

Android använder GLSL ES för OpenGL och SPIR-V för Vulkan. OpenGL ES 3.2 stöder shaders med standard mediump-precision. Vulkan kräver explicit kompilering av GLSL till SPIR-V via glslangValidator. På Android laddas shaders från textresurser eller från kompilerade SPIR-V-filer.

Qualcomm Adreno GPU optimerar shaders på drivrutinsnivå. Rekommendationer: använd mediump för färg och UV, highp endast för positioner; undvik textur sampling i vertex shaders; gruppera beräkningar i vektorer (vec4 istället för 4x float). Enligt Qualcomm (2025) ger dessa optimeringar en förbättring på 30–50%.

Shaders på iOS

iOS använder uteslutande Metal Shading Language. Shaders kompileras till maskinkod tillsammans med applikationen via Xcode. Metal tillhandahåller Shader Debugger och GPU Capture för profilering av shaders. Apple GPU (TBDR) har specifika optimeringar: early fragment test, memoryless render targets och programmerbar blandning.

Enligt Apple WWDC 2024 är det kritiskt för iOS-shaders att använda half istället för float, begränsa registertrycket (max 64 register) och undvika beroende textur sampling. iOS-shaders bör vara kompakta — optimal storlek är 50–100 ALU-instruktioner.

Shaders i Unity och Unreal Engine

Spelmotorerna Unity och Unreal Engine tillhandahåller visuella shader-redigerare (Shader Graph, Material Editor) och abstrakta språk (ShaderLab, USF). Utvecklaren skriver shadern på ett högnivåspråk och motorn kompilerar den för målplattformen. Unity använder HLSL som mellanspråk, Unreal — USF (Unreal Shader Format).

Optimering av shaders

Optimering av shaders — ett nyckelstadium i grafikutveckling för mobila enheter. En dåligt skriven shader kan sänka FPS från 60 till 20. Låt oss titta på huvudreglerna och teknikerna för optimering.

Beräkningsprecision

Använd minimal tillräcklig precision: lowp för färg och UV, mediump för normaler och belysning, highp endast för positioner och matriser. Enligt ARM (2025) är mediump-operationer 2 gånger snabbare än highp på Mali GPU. I GLSL ES ställs detta in via precision-kvalificerare.

Minimera textur sampling

Textur sampling — den dyraste operationen i en shader (10–30 cykler jämfört med 1–2 för en ALU-instruktion). Minska antalet samplingar: kombinera texturer i atlaser, använd lagring i uniform-arrayer istället för texturer, cachla resultat från närliggande pixlar via derivatinstruktioner.

Undvik förgreningar

Dynamiska förgreningar (if med uniform-variabel) minskar prestandan för SIMT-pipelinen. Ersätt förgreningar med matematiska funktioner: mix(), step(), smoothstep() och clamp(). Dessa funktioner exekveras på 1–2 instruktioner, medan en förgrening kan kosta 8–16 instruktioner på grund av tråddivergens.

glsl
// Dåligt: dynamisk förgrening i shader
if (u_enableLight) {
    color *= computeLighting(normal);
}

// Bra: matematisk ersättning av förgrening
color *= mix(1.0, computeLighting(normal),
              float(u_enableLight));

mix() utför linjär interpolation mellan två värden. När u_enableLight=0 returneras 1.0 — färgen ändras inte. När u_enableLight=1 returneras belysningsresultatet. Ingen förgrening — alla trådar exekverar samma kod.

Exempel på shaders

Låt oss titta på praktiska exempel på shaders för mobil utveckling — från enkel skuggning till procedurell texturgenerering. Varje exempel demonstrerar en specifik teknik.

Phong-skuggning (vertex shader)

Phong-modellen — klassisk belysningsmodell med diffus och spegelkomponent. Vertex Shader beräknar belysning för varje vertex, Fragment Shader interpolerar bara resultatet (Gouraud shading). Lämplig för mobila enheter på grund av låg kostnad.

glsl
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
uniform mat4 u_mvp;
uniform mat4 u_modelView;
out vec3 v_color;

void main() {
    vec3 normal = normalize(mat3(u_modelView) * a_normal);
    vec3 lightDir = normalize(vec3(0.0, 1.0, 1.0));
    float diff = max(dot(normal, lightDir), 0.0);
    v_color = vec3(0.8, 0.2, 0.2) * (0.3 + diff * 0.7);
    gl_Position = u_mvp * a_position;
}

Shadern beräknar diffus belysning: skalärprodukten av normalen och ljusriktningen. Resultatet blandas med ambient (0.3) och diffuse (0.7) komponenter. Utför 10–15 ALU-instruktioner per vertex — acceptabelt för 100 000 polygoner vid 60 FPS på en mobil GPU.

Procedurell textur (fragment shader)

Procedurella texturer genereras i Fragment Shader utan att laddas från fil. Sparar videominne och förenklar animation. Exempel — ett schackbräde med variabel cellstorlek. Bara några ALU-instruktioner — minimal belastning på GPU.

glsl
#version 300 es
precision mediump float;
in vec2 v_uv;
uniform float u_cells;
out vec4 fragColor;

void main() {
    vec2 cell = floor(v_uv * u_cells);
    float isWhite = mod(cell.x + cell.y, 2.0);
    fragColor = mix(vec4(0.1, 0.1, 0.1, 1.0),
                     vec4(0.9, 0.9, 0.9, 1.0),
                     isWhite);
}

8 ALU-instruktioner — idealisk shader för mobila enheter. u_cells anger antalet celler per axel. floor och mod — billiga operationer, utförda på 1 cykel på alla mobila GPU:er.

Vanliga frågor

Vad skiljer en shader från ett vanligt C++-program?

Shader körs på GPU i SIMT-läge — en instruktion för hundratals trådar. Vanligt C++-program — på CPU i MIMD-läge. Shadern har inte tillgång till filsystem, in/utmatning och dynamiskt minne. Den tar emot data via buffertar och texturer och returnerar position eller färg.

Vilket shaderspråk ska jag lära mig för mobil utveckling?

GLSL — för OpenGL ES och WebGL, cross-platform. Metal Shading Language — för iOS. HLSL — grunden för Unity och Unreal Engine. Börja med GLSL — förståelse av grunderna överförs till vilket shaderspråk som helst.

Varför är shaders långsamma på mobila enheter?

Huvudorsaker: hög precision (highp istället för mediump), överdriven textur sampling, dynamiska förgreningar och överskridande av registergränsen. Använd RenderDoc eller Xcode GPU Frame Debugger för shader-analys.

Vad är compute shader och vad används det till?

Compute Shader — shader för godtyckliga beräkningar på GPU: partikelfysik, bildbehandling, tygsimulering. Till skillnad från Fragment Shader är den inte bunden till pixlar och kan skriva till godtyckliga buffertar.

Kan man skriva shaders utan kunskaper i programmeringsspråk?

Ja, genom visuella redigerare: Shader Graph i Unity, Material Editor i Unreal Engine eller Metal Shader Converter. De genererar shader-kod baserat på en nodgraf. För djupgående optimering krävs förståelse av shaderspråket.

Sammanfattning

  • Shader — parallellt program för GPU, som bearbetar vertexar, fragment eller godtycklig data massivt.
  • Shadertyper: Vertex, Fragment, Compute, Geometry, Tessellation och Mesh — var och en ansvarig för sitt pipeline-stadium.
  • Språk: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — kompileras till GPU-maskinkod.
  • Mobil specifikation: mediump-precision, minimal textur sampling, inga dynamiska förgreningar.
  • Optimering: mix() istället för if, half-precision, ATF, kombinera texturer i atlaser och förberäkningar på CPU.
  • Användning: Phong-belysning, procedurella texturer, post-effekter, partikelfysik och UI-effekter.
  • Verktyg: RenderDoc, Xcode GPU Debugger, Qualcomm Adreno Profiler och Mali Offline Compiler för shader-analys.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också