60 procedure WarpMouse(x, y: Word); inline; |
60 procedure WarpMouse(x, y: Word); inline; |
61 {$ENDIF} |
61 {$ENDIF} |
62 procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF}; |
62 procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF}; |
63 procedure SetSkyColor(r, g, b: real); |
63 procedure SetSkyColor(r, g, b: real); |
64 |
64 |
65 {$IFDEF GL2} |
|
66 var |
|
67 shaderMain: GLuint; |
|
68 shaderWater: GLuint; |
|
69 {$ENDIF} |
|
70 |
|
71 implementation |
65 implementation |
72 uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, |
66 uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, |
73 uCommands, uPhysFSLayer, uDebug |
67 uCommands, uPhysFSLayer, uDebug |
74 {$IFDEF GL2}, uMatrix{$ENDIF} |
|
75 {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF} |
68 {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF} |
76 {$IF NOT DEFINED(SDL2) AND DEFINED(USE_VIDEO_RECORDING)}, glut {$ENDIF}; |
69 {$IF NOT DEFINED(SDL2) AND DEFINED(USE_VIDEO_RECORDING)}, glut {$ENDIF}; |
77 |
70 |
78 var MaxTextureSize: LongInt; |
71 var |
79 {$IFDEF SDL2} |
72 {$IFDEF SDL2} |
80 SDLwindow: PSDL_Window; |
73 SDLwindow: PSDL_Window; |
81 SDLGLcontext: PSDL_GLContext; |
74 SDLGLcontext: PSDL_GLContext; |
82 {$ELSE} |
75 {$ELSE} |
83 SDLPrimSurface: PSDL_Surface; |
76 SDLPrimSurface: PSDL_Surface; |
790 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); // no alpha channel |
783 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); // no alpha channel |
791 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 16); // buffer should be 16 |
784 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 16); // buffer should be 16 |
792 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // prefer hw rendering |
785 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // prefer hw rendering |
793 end; |
786 end; |
794 |
787 |
795 {$IFDEF GL2} |
|
796 function CompileShader(shaderFile: string; shaderType: GLenum): GLuint; |
|
797 var |
|
798 shader: GLuint; |
|
799 f: Textfile; |
|
800 source, line: AnsiString; |
|
801 sourceA: Pchar; |
|
802 lengthA: GLint; |
|
803 compileResult: GLint; |
|
804 logLength: GLint; |
|
805 log: PChar; |
|
806 begin |
|
807 Assign(f, PathPrefix + cPathz[ptShaders] + '/' + shaderFile); |
|
808 filemode:= 0; // readonly |
|
809 Reset(f); |
|
810 if IOResult <> 0 then |
|
811 begin |
|
812 AddFileLog('Unable to load ' + shaderFile); |
|
813 halt(-1); |
|
814 end; |
|
815 |
|
816 source:=''; |
|
817 while not eof(f) do |
|
818 begin |
|
819 ReadLn(f, line); |
|
820 source:= source + line + #10; |
|
821 end; |
|
822 |
|
823 Close(f); |
|
824 |
|
825 WriteLnToConsole('Compiling shader: ' + PathPrefix + cPathz[ptShaders] + '/' + shaderFile); |
|
826 |
|
827 sourceA:=PChar(source); |
|
828 lengthA:=Length(source); |
|
829 |
|
830 shader:=glCreateShader(shaderType); |
|
831 glShaderSource(shader, 1, @sourceA, @lengthA); |
|
832 glCompileShader(shader); |
|
833 glGetShaderiv(shader, GL_COMPILE_STATUS, @compileResult); |
|
834 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, @logLength); |
|
835 |
|
836 if logLength > 1 then |
|
837 begin |
|
838 log := GetMem(logLength); |
|
839 glGetShaderInfoLog(shader, logLength, nil, log); |
|
840 WriteLnToConsole('========== Compiler log =========='); |
|
841 WriteLnToConsole(shortstring(log)); |
|
842 WriteLnToConsole('==================================='); |
|
843 FreeMem(log, logLength); |
|
844 end; |
|
845 |
|
846 if compileResult <> GL_TRUE then |
|
847 begin |
|
848 WriteLnToConsole('Shader compilation failed, halting'); |
|
849 halt(-1); |
|
850 end; |
|
851 |
|
852 CompileShader:= shader; |
|
853 end; |
|
854 |
|
855 function CompileProgram(shaderName: string): GLuint; |
|
856 var |
|
857 program_: GLuint; |
|
858 vs, fs: GLuint; |
|
859 linkResult: GLint; |
|
860 logLength: GLint; |
|
861 log: PChar; |
|
862 begin |
|
863 program_:= glCreateProgram(); |
|
864 vs:= CompileShader(shaderName + '.vs', GL_VERTEX_SHADER); |
|
865 fs:= CompileShader(shaderName + '.fs', GL_FRAGMENT_SHADER); |
|
866 glAttachShader(program_, vs); |
|
867 glAttachShader(program_, fs); |
|
868 |
|
869 glBindAttribLocation(program_, aVertex, PChar('vertex')); |
|
870 glBindAttribLocation(program_, aTexCoord, PChar('texcoord')); |
|
871 glBindAttribLocation(program_, aColor, PChar('color')); |
|
872 |
|
873 glLinkProgram(program_); |
|
874 glDeleteShader(vs); |
|
875 glDeleteShader(fs); |
|
876 |
|
877 glGetProgramiv(program_, GL_LINK_STATUS, @linkResult); |
|
878 glGetProgramiv(program_, GL_INFO_LOG_LENGTH, @logLength); |
|
879 |
|
880 if logLength > 1 then |
|
881 begin |
|
882 log := GetMem(logLength); |
|
883 glGetProgramInfoLog(program_, logLength, nil, log); |
|
884 WriteLnToConsole('========== Compiler log =========='); |
|
885 WriteLnToConsole(shortstring(log)); |
|
886 WriteLnToConsole('==================================='); |
|
887 FreeMem(log, logLength); |
|
888 end; |
|
889 |
|
890 if linkResult <> GL_TRUE then |
|
891 begin |
|
892 WriteLnToConsole('Linking program failed, halting'); |
|
893 halt(-1); |
|
894 end; |
|
895 |
|
896 CompileProgram:= program_; |
|
897 end; |
|
898 |
|
899 {$ENDIF} |
|
900 |
|
901 procedure SetupOpenGL; |
788 procedure SetupOpenGL; |
902 var buf: array[byte] of char; |
789 var buf: array[byte] of char; |
903 AuxBufNum: LongInt = 0; |
|
904 tmpstr: ansistring; |
|
905 tmpint: LongInt; |
|
906 tmpn: LongInt; |
|
907 begin |
790 begin |
908 |
791 |
909 {$IFDEF SDL2} |
792 {$IFDEF SDL2} |
910 AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); |
793 AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); |
911 {$ELSE} |
794 {$ELSE} |
912 buf[0]:= char(0); // avoid compiler hint |
795 buf[0]:= char(0); // avoid compiler hint |
913 AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))) + ')'); |
796 AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))) + ')'); |
914 {$ENDIF} |
797 {$ENDIF} |
915 |
|
916 AuxBufNum:= AuxBufNum; |
|
917 |
798 |
918 {$IFDEF MOBILE} |
799 {$IFDEF MOBILE} |
919 // TODO: this function creates an opengles1.1 context |
800 // TODO: this function creates an opengles1.1 context |
920 // un-comment below and add proper logic to support opengles2.0 |
801 // un-comment below and add proper logic to support opengles2.0 |
921 //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); |
802 //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); |
924 SDLGLcontext:= SDL_GL_CreateContext(SDLwindow); |
805 SDLGLcontext:= SDL_GL_CreateContext(SDLwindow); |
925 SDLTry(SDLGLcontext <> nil, true); |
806 SDLTry(SDLGLcontext <> nil, true); |
926 SDL_GL_SetSwapInterval(1); |
807 SDL_GL_SetSwapInterval(1); |
927 {$ENDIF} |
808 {$ENDIF} |
928 |
809 |
929 // get the max (h and v) size for textures that the gpu can support |
810 RenderSetup(); |
930 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize); |
|
931 if MaxTextureSize <= 0 then |
|
932 begin |
|
933 MaxTextureSize:= 1024; |
|
934 AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024'); |
|
935 end |
|
936 else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then |
|
937 begin |
|
938 cReducedQuality := cReducedQuality or rqNoBackground; |
|
939 AddFileLog('Texture size too small for backgrounds, disabling.'); |
|
940 end; |
|
941 // everyone loves debugging |
|
942 // find out which gpu we are using (for extension compatibility maybe?) |
|
943 AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER)))); |
|
944 AddFileLog(' |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR)))); |
|
945 AddFileLog(' |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION)))); |
|
946 AddFileLog(' |----- Texture Size: ' + inttostr(MaxTextureSize)); |
|
947 {$IFDEF USE_VIDEO_RECORDING} |
|
948 glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum); |
|
949 AddFileLog(' |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum)); |
|
950 {$ENDIF} |
|
951 {$IFNDEF PAS2C} |
|
952 AddFileLog(' \----- Extensions: '); |
|
953 |
|
954 // fetch extentions and store them in string |
|
955 tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS))); |
|
956 tmpn := WordCount(tmpstr, [' ']); |
|
957 tmpint := 1; |
|
958 |
|
959 repeat |
|
960 begin |
|
961 // print up to 3 extentions per row |
|
962 // ExtractWord will return empty string if index out of range |
|
963 AddFileLog(TrimRight( |
|
964 ExtractWord(tmpint, tmpstr, [' ']) + ' ' + |
|
965 ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' + |
|
966 ExtractWord(tmpint+2, tmpstr, [' ']) |
|
967 )); |
|
968 tmpint := tmpint + 3; |
|
969 end; |
|
970 until (tmpint > tmpn); |
|
971 {$ENDIF} |
|
972 AddFileLog(''); |
|
973 |
|
974 defaultFrame:= 0; |
|
975 {$IFDEF USE_VIDEO_RECORDING} |
|
976 if GameType = gmtRecord then |
|
977 begin |
|
978 if glLoadExtension('GL_EXT_framebuffer_object') then |
|
979 begin |
|
980 CreateFramebuffer(defaultFrame, depthv, texv); |
|
981 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame); |
|
982 AddFileLog('Using framebuffer for video recording.'); |
|
983 end |
|
984 else if AuxBufNum > 0 then |
|
985 begin |
|
986 glDrawBuffer(GL_AUX0); |
|
987 glReadBuffer(GL_AUX0); |
|
988 AddFileLog('Using auxiliary buffer for video recording.'); |
|
989 end |
|
990 else |
|
991 begin |
|
992 glDrawBuffer(GL_BACK); |
|
993 glReadBuffer(GL_BACK); |
|
994 AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.'); |
|
995 end; |
|
996 end; |
|
997 {$ENDIF} |
|
998 |
|
999 {$IFDEF GL2} |
|
1000 |
|
1001 {$IFDEF PAS2C} |
|
1002 err := glewInit(); |
|
1003 if err <> GLEW_OK then |
|
1004 begin |
|
1005 WriteLnToConsole('Failed to initialize GLEW.'); |
|
1006 halt; |
|
1007 end; |
|
1008 {$ENDIF} |
|
1009 |
|
1010 {$IFNDEF PAS2C} |
|
1011 if not Load_GL_VERSION_2_0 then |
|
1012 halt; |
|
1013 {$ENDIF} |
|
1014 |
|
1015 shaderWater:= CompileProgram('water'); |
|
1016 glUseProgram(shaderWater); |
|
1017 glUniform1i(glGetUniformLocation(shaderWater, pchar('tex0')), 0); |
|
1018 uWaterMVPLocation:= glGetUniformLocation(shaderWater, pchar('mvp')); |
|
1019 |
|
1020 shaderMain:= CompileProgram('default'); |
|
1021 glUseProgram(shaderMain); |
|
1022 glUniform1i(glGetUniformLocation(shaderMain, pchar('tex0')), 0); |
|
1023 uMainMVPLocation:= glGetUniformLocation(shaderMain, pchar('mvp')); |
|
1024 uMainTintLocation:= glGetUniformLocation(shaderMain, pchar('tint')); |
|
1025 |
|
1026 uCurrentMVPLocation:= uMainMVPLocation; |
|
1027 |
|
1028 Tint(255, 255, 255, 255); |
|
1029 UpdateModelviewProjection; |
|
1030 {$ENDIF} |
|
1031 |
|
1032 {$IFNDEF USE_S3D_RENDERING} |
|
1033 if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then |
|
1034 begin |
|
1035 // prepare left and right frame buffers and associated textures |
|
1036 if glLoadExtension('GL_EXT_framebuffer_object') then |
|
1037 begin |
|
1038 CreateFramebuffer(framel, depthl, texl); |
|
1039 CreateFramebuffer(framer, depthr, texr); |
|
1040 |
|
1041 // reset |
|
1042 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame) |
|
1043 end |
|
1044 else |
|
1045 cStereoMode:= smNone; |
|
1046 end; |
|
1047 {$ENDIF} |
|
1048 |
|
1049 // set view port to whole window |
|
1050 glViewport(0, 0, cScreenWidth, cScreenHeight); |
|
1051 |
|
1052 {$IFDEF GL2} |
|
1053 uMatrix.initModule; |
|
1054 hglMatrixMode(MATRIX_MODELVIEW); |
|
1055 // prepare default translation/scaling |
|
1056 hglLoadIdentity(); |
|
1057 hglScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0); |
|
1058 hglTranslatef(0, -cScreenHeight / 2, 0); |
|
1059 |
|
1060 EnableTexture(True); |
|
1061 |
|
1062 glEnableVertexAttribArray(aVertex); |
|
1063 glEnableVertexAttribArray(aTexCoord); |
|
1064 glGenBuffers(1, @vBuffer); |
|
1065 glGenBuffers(1, @tBuffer); |
|
1066 glGenBuffers(1, @cBuffer); |
|
1067 {$ELSE} |
|
1068 glMatrixMode(GL_MODELVIEW); |
|
1069 // prepare default translation/scaling |
|
1070 glLoadIdentity(); |
|
1071 glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0); |
|
1072 glTranslatef(0, -cScreenHeight / 2, 0); |
|
1073 |
|
1074 // disable/lower perspective correction (will not need it anyway) |
|
1075 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); |
|
1076 // disable dithering |
|
1077 glDisable(GL_DITHER); |
|
1078 // enable common states by default as they save a lot |
|
1079 glEnable(GL_TEXTURE_2D); |
|
1080 glEnableClientState(GL_VERTEX_ARRAY); |
|
1081 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
1082 {$ENDIF} |
|
1083 |
|
1084 // enable alpha blending |
|
1085 glEnable(GL_BLEND); |
|
1086 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
1087 // disable/lower perspective correction (will not need it anyway) |
|
1088 end; |
811 end; |
1089 |
812 |
1090 (* |
813 (* |
1091 procedure UpdateProjection; |
814 procedure UpdateProjection; |
1092 var |
815 var |