So let's take it step by step, let's keep it clear, shall we? Therefore, I will add the first change now, when there is another, I will add another, and so on.
So. @MasterGy, I found out that fog in OpenGL can only be turned off or on. I thought about it and realized that this is actually enough for me. But - not quite. First, a 2D program that explains the function of how to determine the intensity of the fog and whether we should actually turn it on or not. Do you know the CIRCLE command? There's a little genius thing in the help that just needed a little tweaking for OpenGL use.
Run this simple thing. A circle is drawn. Move the mouse to the middle. In the middle, the function returns 1 - this means that you are in the middle of the fog, so the fog will be thickest here. And on the edges you are somewhere around zero values.
How simple! You have a smooth onset of fog! Well, but if it will work in OpenGL?
I had to wrestle with it a bit, but I finally convinced OpenGL. So focus on lines 36 to 38, this is where you can set the color of the fog, then skip the _GL sub because initialization must be done first in the INIT2 sub on lines 242 and 244, notice line 243, it's moved to the main _GL loop just because to allow for a smooth onset and retreat of the fog. Then look in SUB _GL on lines 118 to 128, where the function I showed you a moment ago in 2D works for the 3D world.
And I ask: Who can guess what other clever uses in 3D the IsOnPos function offers us? Hmmmm?
After all, MUSIC. Imagine a radio placed in free space. The closer you are, the louder it will play. Amazing, huh?
Well, let's calm down a bit and imagine that the radio is placed in the room. And we have calculations.... echo according to the room, sound attenuation according to the walls... but it is enough to place it in a free space.
You have to be careful to set GL_FOG_START and GL_FOG_END correctly, or you will come out of the fog and the object in the distance will be seen as if there was no fog at all (the object must be in the range of GL_FOG_START to GL_FOG_END for this to not happen.
All files in attachment - this time is also world.txt file modified. Zip contains none EXE files, just source code, textures and txt file.
So. @MasterGy, I found out that fog in OpenGL can only be turned off or on. I thought about it and realized that this is actually enough for me. But - not quite. First, a 2D program that explains the function of how to determine the intensity of the fog and whether we should actually turn it on or not. Do you know the CIRCLE command? There's a little genius thing in the help that just needed a little tweaking for OpenGL use.
Code: (Select All)
SCREEN _NEWIMAGE(800, 600, 32)
DO
CLS
LOCATE 1
WHILE _MOUSEINPUT: WEND
X& = _MOUSEX
Y& = _MOUSEY
CIRCLE (400, 300), 150
PRINT IsOnPos(X&, Y&, 400, 300, 150)
_DISPLAY
_LIMIT 20
LOOP
FUNCTION IsOnPos (Walker_Xpos, Walker_Zpos, PointX, PointZ, radius)
xy& = ((Walker_Xpos - PointX) ^ 2) + ((Walker_Zpos - PointZ) ^ 2) 'Pythagorean theorem
IF radius ^ 2 >= xy& THEN IsOnPos = (radius ^ 2 - xy&) / radius ^ 2 ELSE IsOnPos = 0
END FUNCTION
Run this simple thing. A circle is drawn. Move the mouse to the middle. In the middle, the function returns 1 - this means that you are in the middle of the fog, so the fog will be thickest here. And on the edges you are somewhere around zero values.
How simple! You have a smooth onset of fog! Well, but if it will work in OpenGL?
I had to wrestle with it a bit, but I finally convinced OpenGL. So focus on lines 36 to 38, this is where you can set the color of the fog, then skip the _GL sub because initialization must be done first in the INIT2 sub on lines 242 and 244, notice line 243, it's moved to the main _GL loop just because to allow for a smooth onset and retreat of the fog. Then look in SUB _GL on lines 118 to 128, where the function I showed you a moment ago in 2D works for the 3D world.
And I ask: Who can guess what other clever uses in 3D the IsOnPos function offers us? Hmmmm?
After all, MUSIC. Imagine a radio placed in free space. The closer you are, the louder it will play. Amazing, huh?
Well, let's calm down a bit and imagine that the radio is placed in the room. And we have calculations.... echo according to the room, sound attenuation according to the walls... but it is enough to place it in a free space.
You have to be careful to set GL_FOG_START and GL_FOG_END correctly, or you will come out of the fog and the object in the distance will be seen as if there was no fog at all (the object must be in the range of GL_FOG_START to GL_FOG_END for this to not happen.
All files in attachment - this time is also world.txt file modified. Zip contains none EXE files, just source code, textures and txt file.
Code: (Select All)
Declare CustomType Library
Sub gluBuild2DMipmaps (ByVal Target As _Unsigned Long, Byval iFormat As Long, Byval Wdth As Long, Byval Hght As Long, Byval format As _Unsigned Long, Byval typ As _Unsigned Long, Byval dat As _Offset)
End Declare
Type GL_Loader ' array for loading textures
PointerGL As Long
TextureName As String
Filtering As _Unsigned _Byte
End Type
ReDim Shared GLL(0) As GL_Loader, t As Long
Dim Shared GL_InitInfo As _Byte ' is need for OpenGL init
Dim Shared ExitSignal As _Byte ' is need for correct OpenGL exit when program end
'World3D coordinates array
Type Triangle
TextureX As Single
TextureY As Single
VertexX As Single
VertexY As Single
VertexZ As Single
End Type
'World3D texture array
Type Texture_T
FileName As String ' texture file name
Filter As _Byte ' used texture filtering
GL_Pointer As _Unsigned Long ' GL pointer (handle) for texture
End Type
ReDim Shared Triangles(0) As Triangle
ReDim Shared TriTextures(0) As Texture_T
Dim Shared Xpos, Zpos, Yrot, LookUpDown, WalkBias, Blend
'---FOG---
Dim Shared Fog, FogQuality
Dim Shared FogColor(3)
FogColor(0) = 0.5: FogColor(1) = 0.5: FogColor(2) = 0.5: FogColor(3) = 1
'---///---
_DisplayOrder _GLRender , _Software
_Title "World 3D"
LoadWorld "world.txt", Triangles(), TriTextures() 'just read TXT file and save coordinates to array Triangles and texture file names to array TriTextures for us
'next step then is in _GL SUB - it call Init2 and there are all textures loaded to RAM
Const piover180 = 0.0174532925F 'the same function as _D2R or 3.14/180
Screen _NewImage(1024, 768, 32)
Print "Welcome back in 2D world :) Press Alt + F4 to end!"
_MouseHide
Do
i& = _KeyHit
While _MouseInput
LookUpDown = LookUpDown + _MouseMovementY / 5 'Look up/down with mouse, angle is not locked!
Heading = Heading - _MouseMovementX / 5: Yrot = Heading 'rotation left/right using mouse
_MouseMove _Width / 2, _Height / 2
Wend
Select Case i&
Case 20480 'arrow up
Xpos = Xpos + Sin(Heading * piover180) * 0.05F
Zpos = Zpos + Cos(Heading * piover180) * 0.05F
If WalkBiasAngle >= 359.0F Then
WalkBiasAngle = 0.0F
Else
WalkBiasAngle = WalkBiasAngle + 10
End If
WalkBias = Sin(WalkBiasAngle * piover180) / 20.0F
Case 18432 'arrow down
Xpos = Xpos - Sin(Heading * piover180) * 0.05F
Zpos = Zpos - Cos(Heading * piover180) * 0.05F
If WalkBiasAngle <= 1.0F Then
WalkBiasAngle = 359.0F
Else
WalkBiasAngle = WalkBiasAngle - 10
End If
WalkBias = Sin(WalkBiasAngle * piover180) / 20.0F
Case 19200 'arrow left
Heading = Heading + 1
Yrot = Heading
Case 19712 'arrow right
Heading = Heading - 1
Yrot = Heading
Case 81, 113 'Q - look up
LookUpDown = LookUpDown - 1
Case 65, 97 'A - look down
LookUpDown = LookUpDown + 1
Case 66, 98 'B
Blend = Not Blend
End Select '
If ExitSignal Then System
_Limit 50
Loop
Sub _GL ()
Init2
GL_Init
'----- fog -----
' X Z radius
TestFog = IsOnPos(Xpos, Zpos, 0, -6, 7)
If TestFog Then
_glFogf _GL_FOG_DENSITY, TestFog / 2 ' fog density - Maximal TestFog Value is 1, so maximal FOG level is 1/2 = 50 percent.
_glHint _GL_FOG_HINT, _GL_NICEST ' fog Quality
_glFogf _GL_FOG_START, -6.0F ' fog begin in depth - axis z 'both this values are calculated for CAMERA
_glFogf _GL_FOG_END, 6.0F ' fog end in depth - axis z
End If
'-----------------------
_glClear _GL_COLOR_BUFFER_BIT And _GL_DEPTH_BUFFER_BIT 'Clear screen and depth buffer
_glMatrixMode _GL_PROJECTION ' Set projection matrix - TRY comment this five rows and then run it. Black screen occur. For view just something then must be depth set to -1 (Z parameter in _glTranslateF)
_glLoadIdentity ' Reset matrix
_gluPerspective 45.0F, _Width / _Height, 0.1F, 100.0F ' Perspective calculation
_glMatrixMode _GL_MODELVIEW ' set modelview matrix
texture = TriTextures(0).GL_Pointer
'-------------------------------
Locate 1: Print Xpos, Zpos, TestFog
'-------------------------------
Xtrans = -Xpos 'for walking in X axis
Ztrans = -Zpos 'for walking in Z axis
Ytrans = -WalkBias - 0.25F 'simulation steps
SceneRotY = 360.0F - Yrot 'angle direction of view
_glRotatef LookUpDown, 1.0F, 0.0F, 0.0F 'rotation i X axis - view up and down
_glRotatef SceneRotY, 0.0F, 1.0F, 0.0F 'rotation in Y axis - rotation to left / right
_glTranslatef Xtrans, Ytrans, Ztrans ' move to position (shift) in scene
Triangles = UBound(Triangles) - 3 'total triangles used in txt file
TriTextures_i = -1
For l = 0 To Triangles Step 3 'step 3 - because triangle = 3 vertexes
If l Mod 6 = 0 Then ' 6 is 6 vertexes for 2 triangle (1 quad)
If TriTextures_i + 1 < UBound(TriTextures) Then 'if in texture array index is not UBOUND
If TriTextures(TriTextures_i + 1).GL_Pointer > 0 Then 'if tritexture array contains next valid texture
TriTextures_i = TriTextures_i + 1 ' increase index
texture = TriTextures(TriTextures_i).GL_Pointer ' insert next texture
End If
End If
End If
_glBindTexture _GL_TEXTURE_2D, texture 'tohle bude ve smycce vzdy po sesti bodech (6 bodu = 2 trojuhelniky)
_glBegin _GL_TRIANGLES
_glNormal3f 0.0F, 0.0F, 1.0F 'for light
X_m = Triangles(l).VertexX
Y_m = Triangles(l).VertexY
Z_m = Triangles(l).VertexZ
U_m = Triangles(l).TextureX
V_m = Triangles(l).TextureY
_glTexCoord2f U_m, V_m ' place texture first vertex
_glVertex3f X_m, Y_m, Z_m ' place triangle first vertex
X_m = Triangles(l + 1).VertexX
Y_m = Triangles(l + 1).VertexY
Z_m = Triangles(l + 1).VertexZ
U_m = Triangles(l + 1).TextureX
V_m = Triangles(l + 1).TextureY
_glTexCoord2f U_m, V_m ' place texture second vertex
_glVertex3f X_m, Y_m, Z_m ' place triangle second vertex
X_m = Triangles(l + 2).VertexX
Y_m = Triangles(l + 2).VertexY
Z_m = Triangles(l + 2).VertexZ
U_m = Triangles(l + 2).TextureX
V_m = Triangles(l + 2).TextureY
_glTexCoord2f U_m, V_m ' place texture third vertex
_glVertex3f X_m, Y_m, Z_m ' place triangle third vertex
_glEnd
Next
If _Exit Then
' DeleteTexture t 'if program end, first free texture from memory, then exit from GL and return to main loop
KillAllTextures
_glClear _GL_COLOR_BUFFER_BIT
ExitSignal = Not 0
Exit Sub
End If
End Sub
Sub GL_Init
If GL_InitInfo = 0 Then
_glViewport 0, 0, _Width, _Height
GL_InitInfo = 1
End If
End Sub
Sub Init2
_glEnable _GL_TEXTURE_2D 'allow texture maping
_glBlendFunc _GL_SRC_ALPHA, _GL_ONE 'blending type for transparency
_glClearColor 0.0, 0.0, 0.0, 0.5 'Black background
_glClearDepth 1.0F ' depth buffer settings
_glDepthFunc _GL_LESS ' depth testing type
_glEnable _GL_DEPTH_TEST ' enable depth testing
_glShadeModel _GL_SMOOTH 'allow smooth shading
_glHint _GL_PERSPECTIVE_CORRECTION_HINT, _GL_NICEST ' best perspective projection
If Blend Then
_glEnable _GL_BLEND
Else
_glDisable _GL_BLEND
End If
If GL_InitInfo = 0 Then
For l = 0 To UBound(TriTextures)
If Len(TriTextures(l).FileName) Then t = LoadTexture(TriTextures(l).FileName, 1)
TriTextures(l).GL_Pointer = t
TriTextures(l).Filter = 1
Next l
'---- fog ----
_glFogfv _GL_FOG_COLOR, _Offset(FogColor()) 'fog color
' _glFogf _GL_FOG_DENSITY, FogLevel 'fog density
_glHint _GL_FOG_HINT, _GL_DONT_CARE 'middle fog quality
_glEnable _GL_FOG
'---- ---- ----
End If
End Sub
Sub DeleteTexture (nr As Long)
For P = LBound(GLL) To UBound(GLL)
If GLL(P).PointerGL = nr Then
Dim DEL As Long
DEL = GLL(P).PointerGL
_glDeleteTextures 1, _Offset(DEL)
Exit Sub
End If
Next
End Sub
Sub KillAllTextures
For P = LBound(GLL) To UBound(GLL)
If GLL(P).PointerGL > 0 Then
DeleteTexture P
GLL(P).PointerGL = 0
End If
Next P
End Sub
Function LoadTexture (image As String, Filter As _Unsigned _Byte)
If GL_InitInfo = 0 Then GL_Init
If _FileExists(image) Then
TT = 0
Do Until TT = UBound(GLL)
If GLL(TT).TextureName = image$ And GLL(TT).Filtering = Filter Then
LoadTexture = GLL(TT).PointerGL 'prevent memory leak loading next and next texture again and angain...
Exit Function
End If
TT = TT + 1
Loop
tex& = _LoadImage(image$, 32)
_ClearColor _RGB32(255, 255, 0), tex&
texinv& = _NewImage(_Width(tex&), _Height(tex&), 32)
_PutImage (0, _Height(tex&))-(_Width(tex&), 0), tex&, texinv&
ni& = _CopyImage(texinv&, 32) '_NewImage(32, 32, 32)
Dim Texture As _Unsigned Long
_glGenTextures 1, _Offset(Texture) 'generate our texture handle (reserve place in memory for new texture)
_glBindTexture _GL_TEXTURE_2D, Texture 'select our texture handle (set this texture for use)
Dim m As _MEM
m = _MemImage(texinv&)
Dim n As _MEM
n = _MemImage(ni&)
Select Case Filter
Case -1
'set our texture wrapping
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_S, _GL_REPEAT
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_T, _GL_REPEAT
Case 0
'set out texture filtering
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_NEAREST 'for scaling up
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_NEAREST 'for scaling down
Case 1
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR 'for scaling up
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR 'for scaling down
Case 2 'works....not sure, if this output is correct
'gluBuild2DMipmaps(GL_TEXTURE_2D, pic->bpp/8, pic->width, pic->height, textureType, GL_UNSIGNED_BYTE, pic->data);
gluBuild2DMipmaps _GL_TEXTURE_2D, 4, _Width(ni&), _Height(ni&), _GL_RGB, _GL_UNSIGNED_BYTE, _Offset(Texture)
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR_MIPMAP_NEAREST 'for scaling up
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR ' IF IS USED _GL_LINEAR_MIMAP_NEAREST here, program crash. Is it correct? -?-
'
_glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGB, _Width(ni&), _Height(ni&), 0, _GL_BGRA_EXT, _GL_UNSIGNED_BYTE, n.OFFSET
_FreeImage tex&
_MemFree n
'_FreeImage ni&
GoTo saveit
'gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
End Select
_FreeImage tex&
_glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGB, _Width(texinv&), _Height(texinv&), 0, _GL_BGRA_EXT, _GL_UNSIGNED_BYTE, m.OFFSET
saveit:
U = UBound(GLL)
GLL(U).PointerGL = Texture
GLL(U).TextureName = image
GLL(U).Filtering = Filter
ReDim _Preserve GLL(U + 1) As GL_Loader
_MemFree m
Else
Print "LoadTexture Error: "; image$; " - file not found."
End If
LoadTexture = Texture
End Function
Sub LoadWorld (txtFile As String, Triangles() As Triangle, TriTextures() As Texture_T)
file$ = "world.txt"
If _FileExists(file$) Then
ReDim Num(4) As Single
ff = FreeFile
Open file$ For Input As ff
While Not EOF(ff)
radek = radek + 1
Line Input #ff, t$
t$ = t$ + " " ' add space to end line for right detection all numbers in the row
i = InStr(1, t$, "NUMPOLLIES")
If i Then
Print "id: NUMPOLLIES found"
separator = InStr(i + 1, t$, " ")
NumOfTriangles = Val(Mid$(t$, separator, Len(t$) - separator))
Print "Triangles:"; NumOfTriangles
ReDim Triangles(NumOfTriangles * 3) As Triangle
ReDim TriTextures(NumOfTriangles) As Texture_T
i = 0
GoTo NextRow
End If
If InStr(1, t$, "/") = 0 Then 'row contains none C comment
If Len(_Trim$(t$)) Then ' row is not empty
n$ = ""
For r = 1 To Len(t$)
ch = Asc(t$, r) '34 jsou uvozovky
Select Case ch
Case 48 To 57, 45, 46 '0 to 9 . -
num$ = num$ + Chr$(ch)
Case 32
If Len(num$) Then 'kdyz num$ obsahuje ciselnou hodnotu a dalsi znak je mezera
' Print num$
' Sleep
Num(num_i) = Val(num$)
num$ = ""
If num_i = 4 Then
num_i = 0 '0 to 4 for 5 number on 1 row
Else
num_i = num_i + 1
End If
End If
Case 34 'narazil na uvozovky
next34 = InStr(r + 1, t$, Chr$(34))
' Print r, next34
TextureName$ = Mid$(t$, r + 1, next34 - r - 1) 'vraci jmeno textury bez uvozovek
Exit For
End Select
Next r 'loop for 1 row
Triangles(Tri_i).TextureX = Num(3) 'records in text file: Xvertex, Yvertex, Zvertex, TextureX, TextureY, "texturefilename" (if is changed)
Triangles(Tri_i).TextureY = Num(4)
Triangles(Tri_i).VertexX = Num(0)
Triangles(Tri_i).VertexY = Num(1)
Triangles(Tri_i).VertexZ = Num(2)
Tri_i = Tri_i + 1
'Print radek, Tri_i
'Sleep
If Len(TextureName$) Then
' Print TextureName$
TriTextures(TriTex_i).FileName = TextureName$
TriTex_i = TriTex_i + 1
TextureName$ = ""
End If
ReDim Num(4) As Single 'clear array for read next values
Else
GoTo NextRow 'if row is empty, read next row from file
End If
Else
GoTo NextRow ' if row contains C comment separated with // (or just /), read next row from file
End If
NextRow:
Wend
Else
Print "File world.txt not found.": End
End If
Close ff
End Sub
Function IsOnPos (Walker_Xpos, Walker_Zpos, PointX, PointZ, radius)
xy& = ((Walker_Xpos - PointX) ^ 2) + ((Walker_Zpos - PointZ) ^ 2) 'Pythagorean theorem
If radius ^ 2 >= xy& Then IsOnPos = (radius ^ 2 - xy&) / radius ^ 2 Else IsOnPos = 0
End Function